aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/include/protobuf/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDedicatedTest/include/protobuf/compiler')
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.cc168
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.h115
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/code_generator.cc137
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/code_generator.h206
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.cc2616
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.h462
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface_unittest.cc2760
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc195
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.cc438
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.h105
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.cc406
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.h115
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.cc189
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.h95
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.cc391
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.h242
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.cc1419
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.h208
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.cc271
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.h106
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.cc1497
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.h971
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.cc334
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.h78
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.cc4584
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.h231
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.cc892
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.h144
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_layout_helper.h64
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_move_unittest.cc169
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_names.h96
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_options.h95
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.cc228
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.h65
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.cc1303
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.h199
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_plugin_unittest.cc236
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.cc505
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.h116
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.cc327
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.h122
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.cc915
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.h127
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto184
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_large_enum_value.proto43
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.cc134
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.h51
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.inc2234
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/cpp/metadata_test.cc161
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc194
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.cc116
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.h51
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.cc99
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.h66
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.cc135
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.h83
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.cc459
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.h111
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.cc112
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.h70
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator_unittest.cc70
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.cc592
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.h195
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.cc152
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.h75
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc779
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.h94
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.cc293
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.h93
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_names.h109
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_options.h81
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.cc349
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.h97
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.cc330
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.h75
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.cc148
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.h79
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.cc174
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.h79
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc145
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.h75
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.cc75
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.h71
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.cc308
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.h99
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/importer.cc524
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/importer.h336
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/importer_unittest.cc548
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.cc202
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.h113
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.cc435
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.h101
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment_unittest.cc67
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.cc391
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.h100
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.cc1176
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.h161
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.cc918
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.h140
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.cc235
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.h98
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.cc172
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.h115
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.cc115
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.h75
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.cc312
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.h191
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.cc734
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.h125
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.cc211
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.h76
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.cc86
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.h103
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.cc1100
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.h459
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.cc162
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.h72
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.cc876
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.h82
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.cc909
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.h74
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.cc1729
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.h153
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.cc712
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.h89
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.cc151
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.h86
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.cc1494
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.h179
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.cc884
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.h140
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.cc977
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.h86
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.cc380
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.h153
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_names.h100
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_options.h73
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_plugin_unittest.cc119
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.cc1111
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.h162
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.cc779
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.h141
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.cc474
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.h139
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.cc198
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.h90
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.cc1190
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.h160
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.cc864
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.h139
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.cc3941
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.h336
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.cc270
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.h43
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/main.cc113
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.cc384
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.h136
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc260
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h71
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc149
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h80
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc156
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h67
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc475
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h194
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc610
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h82
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc276
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h79
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc1960
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h347
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc385
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc189
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h71
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc636
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h99
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc107
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h87
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h197
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc140
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h76
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc190
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h95
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/package_info.h63
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/parser.cc2445
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/parser.h603
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/parser_unittest.cc3681
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.cc2325
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.h92
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/plugin.cc200
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/plugin.h95
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.cc1584
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.h1909
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/plugin.proto183
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.cc1577
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.h193
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/python/python_plugin_unittest.cc161
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto70
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb79
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto71
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto5
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb80
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto9
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto9
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb20
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb20
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto7
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb20
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc575
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h67
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc145
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/scc.h164
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/subprocess.cc475
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/subprocess.h113
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/test_plugin.cc61
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/zip_output_unittest.sh100
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.cc195
-rw-r--r--NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.h65
218 files changed, 87190 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.cc b/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.cc
new file mode 100644
index 00000000..0ffa4c08
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.cc
@@ -0,0 +1,168 @@
+// 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 <compiler/annotation_test_util.h>
+
+#include <cstdint>
+#include <memory>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/code_generator.h>
+#include <compiler/command_line_interface.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <io/zero_copy_stream_impl_lite.h>
+#include <descriptor.pb.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace annotation_test_util {
+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 std::string& parameter, GeneratorContext* context,
+ std::string* error) const {
+ file->CopyTo(file_);
+ return true;
+ }
+
+ private:
+ FileDescriptorProto* file_;
+};
+} // namespace
+
+void AddFile(const std::string& filename, const std::string& data) {
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
+ true));
+}
+
+bool RunProtoCompiler(const std::string& filename,
+ const std::string& plugin_specific_args,
+ CommandLineInterface* cli, FileDescriptorProto* file) {
+ cli->SetInputsAreProtoPathRelative(true);
+
+ DescriptorCapturingGenerator capturing_generator(file);
+ cli->RegisterGenerator("--capture_out", &capturing_generator, "");
+
+ std::string proto_path = "-I" + TestTempDir();
+ std::string capture_out = "--capture_out=" + TestTempDir();
+
+ const char* argv[] = {"protoc", proto_path.c_str(),
+ plugin_specific_args.c_str(), capture_out.c_str(),
+ filename.c_str()};
+
+ return cli->Run(5, argv) == 0;
+}
+
+bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info) {
+ std::string data;
+ GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
+ io::ArrayInputStream input(data.data(), data.size());
+ return info->ParseFromZeroCopyStream(&input);
+}
+
+void FindAnnotationsOnPath(
+ const GeneratedCodeInfo& info, const std::string& source_file,
+ const std::vector<int>& path,
+ std::vector<const GeneratedCodeInfo::Annotation*>* annotations) {
+ 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()) {
+ annotations->push_back(annotation);
+ }
+ }
+}
+
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+ const GeneratedCodeInfo& info, const std::string& source_file,
+ const std::vector<int>& path) {
+ std::vector<const GeneratedCodeInfo::Annotation*> annotations;
+ FindAnnotationsOnPath(info, source_file, path, &annotations);
+ if (annotations.empty()) {
+ return NULL;
+ }
+ return annotations[0];
+}
+
+bool AtLeastOneAnnotationMatchesSubstring(
+ const std::string& file_content,
+ const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
+ const std::string& expected_text) {
+ for (std::vector<const GeneratedCodeInfo::Annotation*>::const_iterator
+ i = annotations.begin(),
+ e = annotations.end();
+ i != e; ++i) {
+ const GeneratedCodeInfo::Annotation* annotation = *i;
+ uint32_t begin = annotation->begin();
+ uint32_t end = annotation->end();
+ if (end < begin || end > file_content.size()) {
+ return false;
+ }
+ if (file_content.substr(begin, end - begin) == expected_text) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AnnotationMatchesSubstring(const std::string& file_content,
+ const GeneratedCodeInfo::Annotation* annotation,
+ const std::string& expected_text) {
+ std::vector<const GeneratedCodeInfo::Annotation*> annotations;
+ annotations.push_back(annotation);
+ return AtLeastOneAnnotationMatchesSubstring(file_content, annotations,
+ expected_text);
+}
+} // namespace annotation_test_util
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.h b/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.h
new file mode 100644
index 00000000..2fd179cd
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/annotation_test_util.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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
+
+#include <descriptor.pb.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+// Utilities that assist in writing tests for generator annotations.
+// See java/internal/annotation_unittest.cc for an example.
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace annotation_test_util {
+
+// Struct that contains the file generated from a .proto file and its
+// GeneratedCodeInfo. For example, the Java generator will fill this struct
+// (for some 'foo.proto') with:
+// file_path = "Foo.java"
+// file_content = content of Foo.java
+// file_info = parsed content of Foo.java.pb.meta
+struct ExpectedOutput {
+ std::string file_path;
+ std::string file_content;
+ GeneratedCodeInfo file_info;
+ explicit ExpectedOutput(const std::string& file_path)
+ : file_path(file_path) {}
+};
+
+// Creates a file with name `filename` and content `data` in temp test
+// directory.
+void AddFile(const std::string& filename, const std::string& data);
+
+// Runs proto compiler. Captures proto file structure in FileDescriptorProto.
+// Files will be generated in TestTempDir() folder. Callers of this
+// function must read generated files themselves.
+//
+// filename: source .proto file used to generate code.
+// plugin_specific_args: command line arguments specific to current generator.
+// For Java, this value might be "--java_out=annotate_code:test_temp_dir"
+// cli: instance of command line interface to run generator. See Java's
+// annotation_unittest.cc for an example of how to initialize it.
+// file: output parameter, will be set to the descriptor of the proto file
+// specified in filename.
+bool RunProtoCompiler(const std::string& filename,
+ const std::string& plugin_specific_args,
+ CommandLineInterface* cli, FileDescriptorProto* file);
+
+bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info);
+
+// Finds all of the Annotations for a given source file and path.
+// See Location.path in https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto for
+// explanation of what path vector is.
+void FindAnnotationsOnPath(
+ const GeneratedCodeInfo& info, const std::string& source_file,
+ const std::vector<int>& path,
+ std::vector<const GeneratedCodeInfo::Annotation*>* annotations);
+
+// Finds the Annotation for a given source file and path (or returns null if it
+// couldn't). If there are several annotations for given path, returns the first
+// one. See Location.path in
+// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto for explanation of what path
+// vector is.
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+ const GeneratedCodeInfo& info, const std::string& source_file,
+ const std::vector<int>& path);
+
+// Returns true if at least one of the provided annotations covers a given
+// substring in file_content.
+bool AtLeastOneAnnotationMatchesSubstring(
+ const std::string& file_content,
+ const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
+ const std::string& expected_text);
+
+// Returns true if the provided annotation covers a given substring in
+// file_content.
+bool AnnotationMatchesSubstring(const std::string& file_content,
+ const GeneratedCodeInfo::Annotation* annotation,
+ const std::string& expected_text);
+
+} // namespace annotation_test_util
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.cc
new file mode 100644
index 00000000..fd33d895
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.cc
@@ -0,0 +1,137 @@
+// 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 <compiler/code_generator.h>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/plugin.pb.h>
+#include <descriptor.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+CodeGenerator::~CodeGenerator() {}
+
+bool CodeGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ // Default implementation 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 std::string& filename) {
+ return NULL;
+}
+
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
+ const std::string& filename, const std::string& insertion_point) {
+ GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
+ return NULL; // make compiler happy
+}
+
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo(
+ const std::string& filename, const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& /*info*/) {
+ return OpenForInsert(filename, insertion_point);
+}
+
+void GeneratorContext::ListParsedFiles(
+ 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 std::string& text,
+ std::vector<std::pair<std::string, std::string> >* output) {
+ std::vector<std::string> parts = Split(text, ",", true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ std::string::size_type equals_pos = parts[i].find_first_of('=');
+ std::pair<std::string, std::string> value;
+ if (equals_pos == std::string::npos) {
+ value.first = parts[i];
+ value.second = "";
+ } else {
+ value.first = parts[i].substr(0, equals_pos);
+ value.second = parts[i].substr(equals_pos + 1);
+ }
+ output->push_back(value);
+ }
+}
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+std::string StripProto(const std::string& filename) {
+ if (HasSuffixString(filename, ".protodevel")) {
+ return StripSuffixString(filename, ".protodevel");
+ } else {
+ return StripSuffixString(filename, ".proto");
+ }
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.h
new file mode 100644
index 00000000..ac2cf004
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/code_generator.h
@@ -0,0 +1,206 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Defines the abstract interface implemented by each of the language-specific
+// code generators.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
+
+#include <string>
+#include <utility>
+#include <vector>
+#include <stubs/common.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class ZeroCopyOutputStream;
+}
+class FileDescriptor;
+class GeneratedCodeInfo;
+
+namespace compiler {
+class AccessInfoMap;
+
+class Version;
+
+// Defined in this file.
+class CodeGenerator;
+class GeneratorContext;
+
+// The abstract interface to a class which generates code implementing a
+// particular proto file in a particular language. A number of these may
+// be registered with CommandLineInterface to support various languages.
+class PROTOC_EXPORT CodeGenerator {
+ public:
+ inline CodeGenerator() {}
+ virtual ~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 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.
+ virtual bool Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::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 std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const;
+
+ // This must be kept in sync with plugin.proto. See that file for
+ // documentation on each value.
+ enum Feature {
+ FEATURE_PROTO3_OPTIONAL = 1,
+ };
+
+ // Implement this to indicate what features this code generator supports.
+ //
+ // This must be a bitwise OR of values from the Feature enum above (or zero).
+ virtual uint64_t GetSupportedFeatures() const { return 0; }
+
+ // 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);
+};
+
+// CodeGenerators generate one or more files in a given directory. This
+// abstract interface represents the directory to which the CodeGenerator is
+// to write and other information about the context in which the Generator
+// runs.
+class PROTOC_EXPORT GeneratorContext {
+ public:
+ inline GeneratorContext() {
+ }
+ virtual ~GeneratorContext();
+
+ // Opens the given file, truncating it if it exists, and returns a
+ // ZeroCopyOutputStream that writes to the file. The caller takes ownership
+ // of the returned object. This method never fails (a dummy stream will be
+ // returned instead).
+ //
+ // The filename given should be relative to the root of the source tree.
+ // E.g. the C++ generator, when generating code for "foo/bar.proto", will
+ // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
+ // "foo/" is included in these filenames. The filename is not allowed to
+ // contain "." or ".." components.
+ virtual io::ZeroCopyOutputStream* Open(const std::string& filename) = 0;
+
+ // Similar to Open() but the output will be appended to the file if exists
+ virtual io::ZeroCopyOutputStream* OpenForAppend(const std::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
+ // assert-fails -- it exists only for backwards-compatibility.
+ //
+ // WARNING: This feature is currently EXPERIMENTAL and is subject to change.
+ virtual io::ZeroCopyOutputStream* OpenForInsert(
+ const std::string& filename, const std::string& insertion_point);
+
+ // Similar to OpenForInsert, but if `info` is non-empty, will open (or create)
+ // filename.pb.meta and insert info at the appropriate place with the
+ // necessary shifts. The default implementation ignores `info`.
+ //
+ // WARNING: This feature will be REMOVED in the near future.
+ virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+ const std::string& filename, const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& info);
+
+ // 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(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);
+};
+
+// The type GeneratorContext was once called OutputDirectory. This typedef
+// provides backward compatibility.
+typedef GeneratorContext OutputDirectory;
+
+// Several code generators treat the parameter argument as holding a
+// list of options separated by commas. This helper function parses
+// a set of comma-delimited name/value pairs: e.g.,
+// "foo=bar,baz,qux=corge"
+// parses to the pairs:
+// ("foo", "bar"), ("baz", ""), ("qux", "corge")
+PROTOC_EXPORT void ParseGeneratorParameter(
+ const std::string&, std::vector<std::pair<std::string, std::string> >*);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.cc b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.cc
new file mode 100644
index 00000000..f2209964
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.cc
@@ -0,0 +1,2616 @@
+// 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 <compiler/command_line_interface.h>
+
+#include <cstdint>
+
+#include <stubs/platform_macros.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <fstream>
+#include <iostream>
+
+#include <limits.h> //For PATH_MAX
+
+#include <memory>
+
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#endif
+
+#include <stubs/common.h>
+#include <stubs/logging.h>
+#include <stubs/stringprintf.h>
+#include <compiler/subprocess.h>
+#include <compiler/zip_writer.h>
+#include <compiler/plugin.pb.h>
+#include <compiler/code_generator.h>
+#include <compiler/importer.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.h>
+#include <dynamic_message.h>
+#include <text_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <io/io_win32.h>
+#include <stubs/map_util.h>
+#include <stubs/stl_util.h>
+
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0 // If this isn't defined, the platform doesn't need it.
+#endif
+#endif
+
+namespace {
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::io::win32::access;
+using google::protobuf::io::win32::close;
+using google::protobuf::io::win32::mkdir;
+using google::protobuf::io::win32::open;
+using google::protobuf::io::win32::setmode;
+using google::protobuf::io::win32::write;
+#endif
+
+static const char* kDefaultDirectDependenciesViolationMsg =
+ "File is imported but not declared in --direct_dependencies: %s";
+
+// Returns true if the text looks like a Windows-style absolute path, starting
+// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with
+// copy in importer.cc?
+static bool IsWindowsAbsolutePath(const std::string& text) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+ return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) &&
+ (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1;
+#else
+ return false;
+#endif
+}
+
+void SetFdToTextMode(int fd) {
+#ifdef _WIN32
+ if (setmode(fd, _O_TEXT) == -1) {
+ // This should never happen, I think.
+ GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno);
+ }
+#endif
+ // (Text and binary are the same on non-Windows platforms.)
+}
+
+void SetFdToBinaryMode(int fd) {
+#ifdef _WIN32
+ if (setmode(fd, _O_BINARY) == -1) {
+ // This should never happen, I think.
+ GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_BINARY): " << strerror(errno);
+ }
+#endif
+ // (Text and binary are the same on non-Windows platforms.)
+}
+
+void AddTrailingSlash(std::string* path) {
+ if (!path->empty() && path->at(path->size() - 1) != '/') {
+ path->push_back('/');
+ }
+}
+
+bool VerifyDirectoryExists(const std::string& path) {
+ if (path.empty()) return true;
+
+ if (access(path.c_str(), F_OK) == -1) {
+ std::cerr << path << ": " << strerror(errno) << std::endl;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+// Try to create the parent directory of the given file, creating the parent's
+// parent if necessary, and so on. The full file name is actually
+// (prefix + filename), but we assume |prefix| already exists and only create
+// directories listed in |filename|.
+bool TryCreateParentDirectory(const std::string& prefix,
+ const std::string& filename) {
+ // Recursively create parent directories to the output file.
+ // On Windows, both '/' and '\' are valid path separators.
+ std::vector<std::string> parts =
+ Split(filename, "/\\", true);
+ std::string path_so_far = prefix;
+ for (int i = 0; i < parts.size() - 1; i++) {
+ path_so_far += parts[i];
+ if (mkdir(path_so_far.c_str(), 0777) != 0) {
+ if (errno != EEXIST) {
+ std::cerr << filename << ": while trying to create directory "
+ << path_so_far << ": " << strerror(errno) << std::endl;
+ return false;
+ }
+ }
+ path_so_far += '/';
+ }
+
+ return true;
+}
+
+// Get the absolute path of this protoc binary.
+bool GetProtocAbsolutePath(std::string* path) {
+#ifdef _WIN32
+ char buffer[MAX_PATH];
+ int len = GetModuleFileNameA(NULL, buffer, MAX_PATH);
+#elif defined(__APPLE__)
+ char buffer[PATH_MAX];
+ int len = 0;
+
+ char dirtybuffer[PATH_MAX];
+ uint32_t size = sizeof(dirtybuffer);
+ if (_NSGetExecutablePath(dirtybuffer, &size) == 0) {
+ realpath(dirtybuffer, buffer);
+ len = strlen(buffer);
+ }
+#elif defined(__FreeBSD__)
+ char buffer[PATH_MAX];
+ size_t len = PATH_MAX;
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ if (sysctl(mib, 4, &buffer, &len, NULL, 0) != 0) {
+ len = 0;
+ }
+#else
+ char buffer[PATH_MAX];
+ int len = readlink("/proc/self/exe", buffer, PATH_MAX);
+#endif
+ if (len > 0) {
+ path->assign(buffer, len);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Whether a path is where google/protobuf/descriptor.proto and other well-known
+// type protos are installed.
+bool IsInstalledProtoPath(const std::string& path) {
+ // Checking the descriptor.proto file should be good enough.
+ std::string file_path = path + "/google/protobuf/descriptor.proto";
+ return access(file_path.c_str(), F_OK) != -1;
+}
+
+// Add the paths where google/protobuf/descriptor.proto and other well-known
+// type protos are installed.
+void AddDefaultProtoPaths(
+ std::vector<std::pair<std::string, std::string>>* paths) {
+ // TODO(xiaofeng): The code currently only checks relative paths of where
+ // the protoc binary is installed. We probably should make it handle more
+ // cases than that.
+ std::string path;
+ if (!GetProtocAbsolutePath(&path)) {
+ return;
+ }
+ // Strip the binary name.
+ size_t pos = path.find_last_of("/\\");
+ if (pos == std::string::npos || pos == 0) {
+ return;
+ }
+ path = path.substr(0, pos);
+ // Check the binary's directory.
+ if (IsInstalledProtoPath(path)) {
+ paths->push_back(std::pair<std::string, std::string>("", path));
+ return;
+ }
+ // Check if there is an include subdirectory.
+ if (IsInstalledProtoPath(path + "/include")) {
+ paths->push_back(
+ std::pair<std::string, std::string>("", path + "/include"));
+ return;
+ }
+ // Check if the upper level directory has an "include" subdirectory.
+ pos = path.find_last_of("/\\");
+ if (pos == std::string::npos || pos == 0) {
+ return;
+ }
+ path = path.substr(0, pos);
+ if (IsInstalledProtoPath(path + "/include")) {
+ paths->push_back(
+ std::pair<std::string, std::string>("", path + "/include"));
+ return;
+ }
+}
+
+std::string PluginName(const std::string& plugin_prefix,
+ const std::string& directive) {
+ // Assuming the directive starts with "--" and ends with "_out" or "_opt",
+ // strip the "--" and "_out/_opt" and add the plugin prefix.
+ return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
+}
+
+} // namespace
+
+// A MultiFileErrorCollector that prints errors to stderr.
+class CommandLineInterface::ErrorPrinter
+ : public MultiFileErrorCollector,
+ public io::ErrorCollector,
+ public DescriptorPool::ErrorCollector {
+ public:
+ ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL)
+ : format_(format),
+ tree_(tree),
+ found_errors_(false),
+ found_warnings_(false) {}
+ ~ErrorPrinter() {}
+
+ // implements MultiFileErrorCollector ------------------------------
+ void AddError(const std::string& filename, int line, int column,
+ const std::string& message) override {
+ found_errors_ = true;
+ AddErrorOrWarning(filename, line, column, message, "error", std::cerr);
+ }
+
+ void AddWarning(const std::string& filename, int line, int column,
+ const std::string& message) override {
+ found_warnings_ = true;
+ AddErrorOrWarning(filename, line, column, message, "warning", std::clog);
+ }
+
+ // implements io::ErrorCollector -----------------------------------
+ void AddError(int line, int column, const std::string& message) override {
+ AddError("input", line, column, message);
+ }
+
+ void AddWarning(int line, int column, const std::string& message) override {
+ AddErrorOrWarning("input", line, column, message, "warning", std::clog);
+ }
+
+ // implements DescriptorPool::ErrorCollector-------------------------
+ void AddError(const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) override {
+ AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr);
+ }
+
+ void AddWarning(const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) override {
+ AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog);
+ }
+
+ bool FoundErrors() const { return found_errors_; }
+
+ bool FoundWarnings() const { return found_warnings_; }
+
+ private:
+ void AddErrorOrWarning(const std::string& filename, int line, int column,
+ const std::string& message, const std::string& type,
+ std::ostream& out) {
+ // Print full path when running under MSVS
+ std::string dfile;
+ if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && tree_ != NULL &&
+ tree_->VirtualFileToDiskFile(filename, &dfile)) {
+ out << dfile;
+ } else {
+ out << filename;
+ }
+
+ // Users typically expect 1-based line/column numbers, so we add 1
+ // to each here.
+ if (line != -1) {
+ // Allow for both GCC- and Visual-Studio-compatible output.
+ switch (format_) {
+ case CommandLineInterface::ERROR_FORMAT_GCC:
+ out << ":" << (line + 1) << ":" << (column + 1);
+ break;
+ case CommandLineInterface::ERROR_FORMAT_MSVS:
+ out << "(" << (line + 1) << ") : " << type
+ << " in column=" << (column + 1);
+ break;
+ }
+ }
+
+ if (type == "warning") {
+ out << ": warning: " << message << std::endl;
+ } else {
+ out << ": " << message << std::endl;
+ }
+ }
+
+ const ErrorFormat format_;
+ DiskSourceTree* tree_;
+ bool found_errors_;
+ bool found_warnings_;
+};
+
+// -------------------------------------------------------------------
+
+// A GeneratorContext implementation that buffers files in memory, then dumps
+// them all to disk on demand.
+class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
+ public:
+ GeneratorContextImpl(const std::vector<const FileDescriptor*>& parsed_files);
+
+ // Write all files in the directory to disk at the given output location,
+ // which must end in a '/'.
+ bool WriteAllToDisk(const std::string& prefix);
+
+ // Write the contents of this directory to a ZIP-format archive with the
+ // given name.
+ bool WriteAllToZip(const std::string& filename);
+
+ // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR
+ // format, unless one has already been written.
+ void AddJarManifest();
+
+ // Get name of all output files.
+ void GetOutputFilenames(std::vector<std::string>* output_filenames);
+
+ // implements GeneratorContext --------------------------------------
+ io::ZeroCopyOutputStream* Open(const std::string& filename) override;
+ io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename) override;
+ io::ZeroCopyOutputStream* OpenForInsert(
+ const std::string& filename, const std::string& insertion_point) override;
+ io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+ const std::string& filename, const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& info) override;
+ void ListParsedFiles(std::vector<const FileDescriptor*>* output) override {
+ *output = parsed_files_;
+ }
+
+ private:
+ friend class MemoryOutputStream;
+
+ // The files_ field maps from path keys to file content values. It's a map
+ // instead of an unordered_map so that files are written in order (good when
+ // writing zips).
+ std::map<std::string, std::string> files_;
+ const std::vector<const FileDescriptor*>& parsed_files_;
+ bool had_error_;
+};
+
+class CommandLineInterface::MemoryOutputStream
+ : public io::ZeroCopyOutputStream {
+ public:
+ MemoryOutputStream(GeneratorContextImpl* directory,
+ const std::string& filename, bool append_mode);
+ MemoryOutputStream(GeneratorContextImpl* directory,
+ const std::string& filename,
+ const std::string& insertion_point);
+ MemoryOutputStream(GeneratorContextImpl* directory,
+ const std::string& filename,
+ const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& info);
+ virtual ~MemoryOutputStream();
+
+ // implements ZeroCopyOutputStream ---------------------------------
+ bool Next(void** data, int* size) override {
+ return inner_->Next(data, size);
+ }
+ void BackUp(int count) override { inner_->BackUp(count); }
+ int64_t ByteCount() const override { return inner_->ByteCount(); }
+
+ private:
+ // Checks to see if "filename_.pb.meta" exists in directory_; if so, fixes the
+ // offsets in that GeneratedCodeInfo record to reflect bytes inserted in
+ // filename_ at original offset insertion_offset with length insertion_length.
+ // Also adds in the data from info_to_insert_ with updated offsets governed by
+ // insertion_offset and indent_length. We assume that insertions will not
+ // occur within any given annotated span of text. insertion_content must end
+ // with an endline.
+ void UpdateMetadata(const std::string& insertion_content,
+ size_t insertion_offset, size_t insertion_length,
+ size_t indent_length);
+
+ // Inserts info_to_insert_ into target_info, assuming that the relevant
+ // insertion was made at insertion_offset in file_content with the given
+ // indent_length. insertion_content must end with an endline.
+ void InsertShiftedInfo(const std::string& insertion_content,
+ size_t insertion_offset, size_t indent_length,
+ google::protobuf::GeneratedCodeInfo& target_info);
+
+ // Where to insert the string when it's done.
+ GeneratorContextImpl* directory_;
+ std::string filename_;
+ std::string insertion_point_;
+
+ // The string we're building.
+ std::string data_;
+
+ // Whether we should append the output stream to the existing file.
+ bool append_mode_;
+
+ // StringOutputStream writing to data_.
+ std::unique_ptr<io::StringOutputStream> inner_;
+
+ // The GeneratedCodeInfo to insert at the insertion point.
+ google::protobuf::GeneratedCodeInfo info_to_insert_;
+};
+
+// -------------------------------------------------------------------
+
+CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
+ const std::vector<const FileDescriptor*>& parsed_files)
+ : parsed_files_(parsed_files), had_error_(false) {}
+
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
+ const std::string& prefix) {
+ if (had_error_) {
+ return false;
+ }
+
+ if (!VerifyDirectoryExists(prefix)) {
+ return false;
+ }
+
+ for (const auto& pair : files_) {
+ const std::string& relative_filename = pair.first;
+ const char* data = pair.second.data();
+ int size = pair.second.size();
+
+ if (!TryCreateParentDirectory(prefix, relative_filename)) {
+ return false;
+ }
+ std::string filename = prefix + relative_filename;
+
+ // Create the output file.
+ int file_descriptor;
+ do {
+ file_descriptor =
+ open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (file_descriptor < 0 && errno == EINTR);
+
+ if (file_descriptor < 0) {
+ int error = errno;
+ std::cerr << filename << ": " << strerror(error);
+ return false;
+ }
+
+ // Write the file.
+ while (size > 0) {
+ int write_result;
+ do {
+ write_result = write(file_descriptor, data, size);
+ } while (write_result < 0 && errno == EINTR);
+
+ if (write_result <= 0) {
+ // Write error.
+
+ // FIXME(kenton): According to the man page, if write() returns zero,
+ // there was no error; write() simply did not write anything. It's
+ // unclear under what circumstances this might happen, but presumably
+ // errno won't be set in this case. I am confused as to how such an
+ // event should be handled. For now I'm treating it as an error,
+ // since retrying seems like it could lead to an infinite loop. I
+ // suspect this never actually happens anyway.
+
+ if (write_result < 0) {
+ int error = errno;
+ std::cerr << filename << ": write: " << strerror(error);
+ } else {
+ std::cerr << filename << ": write() returned zero?" << std::endl;
+ }
+ return false;
+ }
+
+ data += write_result;
+ size -= write_result;
+ }
+
+ if (close(file_descriptor) != 0) {
+ int error = errno;
+ std::cerr << filename << ": close: " << strerror(error);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
+ const std::string& filename) {
+ if (had_error_) {
+ return false;
+ }
+
+ // Create the output file.
+ int file_descriptor;
+ do {
+ file_descriptor =
+ open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (file_descriptor < 0 && errno == EINTR);
+
+ if (file_descriptor < 0) {
+ int error = errno;
+ std::cerr << filename << ": " << strerror(error);
+ return false;
+ }
+
+ // Create the ZipWriter
+ io::FileOutputStream stream(file_descriptor);
+ ZipWriter zip_writer(&stream);
+
+ for (const auto& pair : files_) {
+ zip_writer.Write(pair.first, pair.second);
+ }
+
+ zip_writer.WriteDirectory();
+
+ if (stream.GetErrno() != 0) {
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+ return false;
+ }
+
+ if (!stream.Close()) {
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
+ auto pair = files_.insert({"META-INF/MANIFEST.MF", ""});
+ if (pair.second) {
+ pair.first->second =
+ "Manifest-Version: 1.0\n"
+ "Created-By: 1.6.0 (protoc)\n"
+ "\n";
+ }
+}
+
+void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
+ std::vector<std::string>* output_filenames) {
+ for (const auto& pair : files_) {
+ output_filenames->push_back(pair.first);
+ }
+}
+
+io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
+ const std::string& filename) {
+ return new MemoryOutputStream(this, filename, false);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForAppend(
+ const std::string& filename) {
+ return new MemoryOutputStream(this, filename, true);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForInsert(
+ const std::string& filename, const std::string& insertion_point) {
+ return new MemoryOutputStream(this, filename, insertion_point);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForInsertWithGeneratedCodeInfo(
+ const std::string& filename, const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& info) {
+ return new MemoryOutputStream(this, filename, insertion_point, info);
+}
+
+// -------------------------------------------------------------------
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+ GeneratorContextImpl* directory, const std::string& filename,
+ bool append_mode)
+ : directory_(directory),
+ filename_(filename),
+ append_mode_(append_mode),
+ inner_(new io::StringOutputStream(&data_)) {}
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+ GeneratorContextImpl* directory, const std::string& filename,
+ const std::string& insertion_point)
+ : directory_(directory),
+ filename_(filename),
+ insertion_point_(insertion_point),
+ inner_(new io::StringOutputStream(&data_)) {}
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+ GeneratorContextImpl* directory, const std::string& filename,
+ const std::string& insertion_point, const google::protobuf::GeneratedCodeInfo& info)
+ : directory_(directory),
+ filename_(filename),
+ insertion_point_(insertion_point),
+ inner_(new io::StringOutputStream(&data_)),
+ info_to_insert_(info) {}
+
+void CommandLineInterface::MemoryOutputStream::InsertShiftedInfo(
+ const std::string& insertion_content, size_t insertion_offset,
+ size_t indent_length, google::protobuf::GeneratedCodeInfo& target_info) {
+ // Keep track of how much extra data was added for indents before the
+ // current annotation being inserted. `pos` and `source_annotation.begin()`
+ // are offsets in `insertion_content`. `insertion_offset` is updated so that
+ // it can be added to an annotation's `begin` field to reflect that
+ // annotation's updated location after `insertion_content` was inserted into
+ // the target file.
+ size_t pos = 0;
+ insertion_offset += indent_length;
+ for (const auto& source_annotation : info_to_insert_.annotation()) {
+ GeneratedCodeInfo::Annotation* annotation = target_info.add_annotation();
+ int inner_indent = 0;
+ // insertion_content is guaranteed to end in an endline. This last endline
+ // has no effect on indentation.
+ for (; pos < source_annotation.end() && pos < insertion_content.size() - 1;
+ ++pos) {
+ if (insertion_content[pos] == '\n') {
+ if (pos >= source_annotation.begin()) {
+ // The beginning of the annotation is at insertion_offset, but the end
+ // can still move further in the target file.
+ inner_indent += indent_length;
+ } else {
+ insertion_offset += indent_length;
+ }
+ }
+ }
+ *annotation = source_annotation;
+ annotation->set_begin(annotation->begin() + insertion_offset);
+ insertion_offset += inner_indent;
+ annotation->set_end(annotation->end() + insertion_offset);
+ }
+}
+
+void CommandLineInterface::MemoryOutputStream::UpdateMetadata(
+ const std::string& insertion_content, size_t insertion_offset,
+ size_t insertion_length, size_t indent_length) {
+ auto it = directory_->files_.find(filename_ + ".pb.meta");
+ if (it == directory_->files_.end() && info_to_insert_.annotation().empty()) {
+ // No metadata was recorded for this file.
+ return;
+ }
+ GeneratedCodeInfo metadata;
+ bool is_text_format = false;
+ std::string* encoded_data = nullptr;
+ if (it != directory_->files_.end()) {
+ encoded_data = &it->second;
+ // Try to decode a GeneratedCodeInfo proto from the .pb.meta file. It may be
+ // in wire or text format. Keep the same format when the data is written out
+ // later.
+ if (!metadata.ParseFromString(*encoded_data)) {
+ if (!TextFormat::ParseFromString(*encoded_data, &metadata)) {
+ // The metadata is invalid.
+ std::cerr
+ << filename_
+ << ".pb.meta: Could not parse metadata as wire or text format."
+ << std::endl;
+ return;
+ }
+ // Generators that use the public plugin interface emit text-format
+ // metadata (because in the public plugin protocol, file content must be
+ // UTF8-encoded strings).
+ is_text_format = true;
+ }
+ } else {
+ // Create a new file to store the new metadata in info_to_insert_.
+ encoded_data =
+ &directory_->files_.insert({filename_ + ".pb.meta", ""}).first->second;
+ }
+ GeneratedCodeInfo new_metadata;
+ bool crossed_offset = false;
+ size_t to_add = 0;
+ for (const auto& source_annotation : metadata.annotation()) {
+ // The first time an annotation at or after the insertion point is found,
+ // insert the new metadata from info_to_insert_. Shift all annotations
+ // after the new metadata by the length of the text that was inserted
+ // (including any additional indent length).
+ if (source_annotation.begin() >= insertion_offset && !crossed_offset) {
+ crossed_offset = true;
+ InsertShiftedInfo(insertion_content, insertion_offset, indent_length,
+ new_metadata);
+ to_add += insertion_length;
+ }
+ GeneratedCodeInfo::Annotation* annotation = new_metadata.add_annotation();
+ *annotation = source_annotation;
+ annotation->set_begin(annotation->begin() + to_add);
+ annotation->set_end(annotation->end() + to_add);
+ }
+ // If there were never any annotations at or after the insertion point,
+ // make sure to still insert the new metadata from info_to_insert_.
+ if (!crossed_offset) {
+ InsertShiftedInfo(insertion_content, insertion_offset, indent_length,
+ new_metadata);
+ }
+ if (is_text_format) {
+ TextFormat::PrintToString(new_metadata, encoded_data);
+ } else {
+ new_metadata.SerializeToString(encoded_data);
+ }
+}
+
+CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
+ // Make sure all data has been written.
+ inner_.reset();
+
+ // Insert into the directory.
+ auto pair = directory_->files_.insert({filename_, ""});
+ auto it = pair.first;
+ bool already_present = !pair.second;
+
+ if (insertion_point_.empty()) {
+ // This was just a regular Open().
+ if (already_present) {
+ if (append_mode_) {
+ it->second.append(data_);
+ } else {
+ std::cerr << filename_ << ": Tried to write the same file twice."
+ << std::endl;
+ directory_->had_error_ = true;
+ }
+ return;
+ }
+
+ it->second.swap(data_);
+ } else {
+ // This was an OpenForInsert().
+
+ // If the data doesn't end with a clean line break, add one.
+ if (!data_.empty() && data_[data_.size() - 1] != '\n') {
+ data_.push_back('\n');
+ }
+
+ // Find the file we are going to insert into.
+ if (!already_present) {
+ std::cerr << filename_
+ << ": Tried to insert into file that doesn't exist."
+ << std::endl;
+ directory_->had_error_ = true;
+ return;
+ }
+ std::string* target = &it->second;
+
+ // Find the insertion point.
+ std::string magic_string =
+ strings::Substitute("@@protoc_insertion_point($0)", insertion_point_);
+ std::string::size_type pos = target->find(magic_string);
+
+ if (pos == std::string::npos) {
+ std::cerr << filename_ << ": insertion point \"" << insertion_point_
+ << "\" not found." << std::endl;
+ directory_->had_error_ = true;
+ return;
+ }
+
+ if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
+ // Support for inline "/* @@protoc_insertion_point() */"
+ pos = pos - 3;
+ } else {
+ // Seek backwards to the beginning of the line, which is where we will
+ // insert the data. Note that this has the effect of pushing the
+ // insertion point down, so the data is inserted before it. This is
+ // intentional because it means that multiple insertions at the same point
+ // will end up in the expected order in the final output.
+ pos = target->find_last_of('\n', pos);
+ if (pos == std::string::npos) {
+ // Insertion point is on the first line.
+ pos = 0;
+ } else {
+ // Advance to character after '\n'.
+ ++pos;
+ }
+ }
+
+ // Extract indent.
+ std::string indent_(*target, pos,
+ target->find_first_not_of(" \t", pos) - pos);
+
+ if (indent_.empty()) {
+ // No indent. This makes things easier.
+ target->insert(pos, data_);
+ UpdateMetadata(data_, pos, data_.size(), 0);
+ } else {
+ // Calculate how much space we need.
+ int indent_size = 0;
+ for (int i = 0; i < data_.size(); i++) {
+ if (data_[i] == '\n') indent_size += indent_.size();
+ }
+
+ // Make a hole for it.
+ target->insert(pos, data_.size() + indent_size, '\0');
+
+ // Now copy in the data.
+ std::string::size_type data_pos = 0;
+ char* target_ptr = ::google::protobuf::string_as_array(target) + pos;
+ while (data_pos < data_.size()) {
+ // Copy indent.
+ memcpy(target_ptr, indent_.data(), indent_.size());
+ target_ptr += indent_.size();
+
+ // Copy line from data_.
+ // We already guaranteed that data_ ends with a newline (above), so this
+ // search can't fail.
+ std::string::size_type line_length =
+ data_.find_first_of('\n', data_pos) + 1 - data_pos;
+ memcpy(target_ptr, data_.data() + data_pos, line_length);
+ target_ptr += line_length;
+ data_pos += line_length;
+ }
+ UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size());
+
+ GOOGLE_CHECK_EQ(target_ptr,
+ ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size);
+ }
+ }
+}
+
+// ===================================================================
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+const char* const CommandLineInterface::kPathSeparator = ";";
+#else
+const char* const CommandLineInterface::kPathSeparator = ":";
+#endif
+
+CommandLineInterface::CommandLineInterface()
+ : direct_dependencies_violation_msg_(
+ kDefaultDirectDependenciesViolationMsg) {}
+
+CommandLineInterface::~CommandLineInterface() {}
+
+void CommandLineInterface::RegisterGenerator(const std::string& flag_name,
+ CodeGenerator* generator,
+ const std::string& help_text) {
+ GeneratorInfo info;
+ info.flag_name = flag_name;
+ info.generator = generator;
+ info.help_text = help_text;
+ generators_by_flag_name_[flag_name] = info;
+}
+
+void CommandLineInterface::RegisterGenerator(
+ const std::string& flag_name, const std::string& option_flag_name,
+ CodeGenerator* generator, const std::string& help_text) {
+ GeneratorInfo info;
+ info.flag_name = flag_name;
+ info.option_flag_name = option_flag_name;
+ info.generator = generator;
+ info.help_text = help_text;
+ generators_by_flag_name_[flag_name] = info;
+ generators_by_option_name_[option_flag_name] = info;
+}
+
+void CommandLineInterface::AllowPlugins(const std::string& exe_name_prefix) {
+ plugin_prefix_ = exe_name_prefix;
+}
+
+namespace {
+
+bool ContainsProto3Optional(const Descriptor* desc) {
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->has_optional_keyword()) {
+ return true;
+ }
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ if (ContainsProto3Optional(desc->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ContainsProto3Optional(const FileDescriptor* file) {
+ if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (ContainsProto3Optional(file->message_type(i))) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+namespace {
+std::unique_ptr<SimpleDescriptorDatabase>
+PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name);
+}
+
+int CommandLineInterface::Run(int argc, const char* const argv[]) {
+ Clear();
+ switch (ParseArguments(argc, argv)) {
+ case PARSE_ARGUMENT_DONE_AND_EXIT:
+ return 0;
+ case PARSE_ARGUMENT_FAIL:
+ return 1;
+ case PARSE_ARGUMENT_DONE_AND_CONTINUE:
+ break;
+ }
+
+ std::vector<const FileDescriptor*> parsed_files;
+ std::unique_ptr<DiskSourceTree> disk_source_tree;
+ std::unique_ptr<ErrorPrinter> error_collector;
+ std::unique_ptr<DescriptorPool> descriptor_pool;
+
+ // The SimpleDescriptorDatabases here are the constituents of the
+ // MergedDescriptorDatabase descriptor_set_in_database, so this vector is for
+ // managing their lifetimes. Its scope should match descriptor_set_in_database
+ std::vector<std::unique_ptr<SimpleDescriptorDatabase>>
+ databases_per_descriptor_set;
+ std::unique_ptr<MergedDescriptorDatabase> descriptor_set_in_database;
+
+ std::unique_ptr<SourceTreeDescriptorDatabase> source_tree_database;
+
+ // Any --descriptor_set_in FileDescriptorSet objects will be used as a
+ // fallback to input_files on command line, so create that db first.
+ if (!descriptor_set_in_names_.empty()) {
+ for (const std::string& name : descriptor_set_in_names_) {
+ std::unique_ptr<SimpleDescriptorDatabase> database_for_descriptor_set =
+ PopulateSingleSimpleDescriptorDatabase(name);
+ if (!database_for_descriptor_set) {
+ return EXIT_FAILURE;
+ }
+ databases_per_descriptor_set.push_back(
+ std::move(database_for_descriptor_set));
+ }
+
+ std::vector<DescriptorDatabase*> raw_databases_per_descriptor_set;
+ raw_databases_per_descriptor_set.reserve(
+ databases_per_descriptor_set.size());
+ for (const std::unique_ptr<SimpleDescriptorDatabase>& db :
+ databases_per_descriptor_set) {
+ raw_databases_per_descriptor_set.push_back(db.get());
+ }
+ descriptor_set_in_database.reset(
+ new MergedDescriptorDatabase(raw_databases_per_descriptor_set));
+ }
+
+ if (proto_path_.empty()) {
+ // If there are no --proto_path flags, then just look in the specified
+ // --descriptor_set_in files. But first, verify that the input files are
+ // there.
+ if (!VerifyInputFilesInDescriptors(descriptor_set_in_database.get())) {
+ return 1;
+ }
+
+ error_collector.reset(new ErrorPrinter(error_format_));
+ descriptor_pool.reset(new DescriptorPool(descriptor_set_in_database.get(),
+ error_collector.get()));
+ } else {
+ disk_source_tree.reset(new DiskSourceTree());
+ if (!InitializeDiskSourceTree(disk_source_tree.get(),
+ descriptor_set_in_database.get())) {
+ return 1;
+ }
+
+ error_collector.reset(
+ new ErrorPrinter(error_format_, disk_source_tree.get()));
+
+ source_tree_database.reset(new SourceTreeDescriptorDatabase(
+ disk_source_tree.get(), descriptor_set_in_database.get()));
+ source_tree_database->RecordErrorsTo(error_collector.get());
+
+ descriptor_pool.reset(new DescriptorPool(
+ source_tree_database.get(),
+ source_tree_database->GetValidationErrorCollector()));
+ }
+
+ descriptor_pool->EnforceWeakDependencies(true);
+ if (!ParseInputFiles(descriptor_pool.get(), disk_source_tree.get(),
+ &parsed_files)) {
+ return 1;
+ }
+
+
+ // We construct a separate GeneratorContext for each output location. Note
+ // that two code generators may output to the same location, in which case
+ // they should share a single GeneratorContext so that OpenForInsert() works.
+ GeneratorContextMap output_directories;
+
+ // Generate output.
+ if (mode_ == MODE_COMPILE) {
+ for (int i = 0; i < output_directives_.size(); i++) {
+ std::string output_location = output_directives_[i].output_location;
+ if (!HasSuffixString(output_location, ".zip") &&
+ !HasSuffixString(output_location, ".jar") &&
+ !HasSuffixString(output_location, ".srcjar")) {
+ AddTrailingSlash(&output_location);
+ }
+
+ auto& generator = output_directories[output_location];
+
+ if (!generator) {
+ // First time we've seen this output location.
+ generator.reset(new GeneratorContextImpl(parsed_files));
+ }
+
+ if (!GenerateOutput(parsed_files, output_directives_[i],
+ generator.get())) {
+ return 1;
+ }
+ }
+ }
+
+ // Write all output to disk.
+ for (const auto& pair : output_directories) {
+ const std::string& location = pair.first;
+ GeneratorContextImpl* directory = pair.second.get();
+ if (HasSuffixString(location, "/")) {
+ if (!directory->WriteAllToDisk(location)) {
+ return 1;
+ }
+ } else {
+ if (HasSuffixString(location, ".jar")) {
+ directory->AddJarManifest();
+ }
+
+ if (!directory->WriteAllToZip(location)) {
+ return 1;
+ }
+ }
+ }
+
+ if (!dependency_out_name_.empty()) {
+ GOOGLE_DCHECK(disk_source_tree.get());
+ if (!GenerateDependencyManifestFile(parsed_files, output_directories,
+ disk_source_tree.get())) {
+ return 1;
+ }
+ }
+
+ if (!descriptor_set_out_name_.empty()) {
+ if (!WriteDescriptorSet(parsed_files)) {
+ return 1;
+ }
+ }
+
+ if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) {
+ if (codec_type_.empty()) {
+ // HACK: Define an EmptyMessage type to use for decoding.
+ DescriptorPool pool;
+ FileDescriptorProto file;
+ file.set_name("empty_message.proto");
+ file.add_message_type()->set_name("EmptyMessage");
+ GOOGLE_CHECK(pool.BuildFile(file) != NULL);
+ codec_type_ = "EmptyMessage";
+ if (!EncodeOrDecode(&pool)) {
+ return 1;
+ }
+ } else {
+ if (!EncodeOrDecode(descriptor_pool.get())) {
+ return 1;
+ }
+ }
+ }
+
+ if (error_collector->FoundErrors() ||
+ (fatal_warnings_ && error_collector->FoundWarnings())) {
+ return 1;
+ }
+
+ if (mode_ == MODE_PRINT) {
+ switch (print_mode_) {
+ case PRINT_FREE_FIELDS:
+ for (int i = 0; i < parsed_files.size(); ++i) {
+ const FileDescriptor* fd = parsed_files[i];
+ for (int j = 0; j < fd->message_type_count(); ++j) {
+ PrintFreeFieldNumbers(fd->message_type(j));
+ }
+ }
+ break;
+ case PRINT_NONE:
+ GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of "
+ "flag parsing in the CommandLineInterface.";
+ return 1;
+
+ // Do not add a default case.
+ }
+ }
+
+ return 0;
+}
+
+bool CommandLineInterface::InitializeDiskSourceTree(
+ DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) {
+ AddDefaultProtoPaths(&proto_path_);
+
+ // Set up the source tree.
+ for (int i = 0; i < proto_path_.size(); i++) {
+ source_tree->MapPath(proto_path_[i].first, proto_path_[i].second);
+ }
+
+ // Map input files to virtual paths if possible.
+ if (!MakeInputsBeProtoPathRelative(source_tree, fallback_database)) {
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+std::unique_ptr<SimpleDescriptorDatabase>
+PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name) {
+ int fd;
+ do {
+ fd = open(descriptor_set_name.c_str(), O_RDONLY | O_BINARY);
+ } while (fd < 0 && errno == EINTR);
+ if (fd < 0) {
+ std::cerr << descriptor_set_name << ": " << strerror(ENOENT) << std::endl;
+ return nullptr;
+ }
+
+ FileDescriptorSet file_descriptor_set;
+ bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd);
+ if (close(fd) != 0) {
+ std::cerr << descriptor_set_name << ": close: " << strerror(errno)
+ << std::endl;
+ return nullptr;
+ }
+
+ if (!parsed) {
+ std::cerr << descriptor_set_name << ": Unable to parse." << std::endl;
+ return nullptr;
+ }
+
+ std::unique_ptr<SimpleDescriptorDatabase> database{
+ new SimpleDescriptorDatabase()};
+
+ for (int j = 0; j < file_descriptor_set.file_size(); j++) {
+ FileDescriptorProto previously_added_file_descriptor_proto;
+ if (database->FindFileByName(file_descriptor_set.file(j).name(),
+ &previously_added_file_descriptor_proto)) {
+ // already present - skip
+ continue;
+ }
+ if (!database->Add(file_descriptor_set.file(j))) {
+ return nullptr;
+ }
+ }
+ return database;
+}
+
+} // namespace
+
+
+bool CommandLineInterface::VerifyInputFilesInDescriptors(
+ DescriptorDatabase* database) {
+ for (const auto& input_file : input_files_) {
+ FileDescriptorProto file_descriptor;
+ if (!database->FindFileByName(input_file, &file_descriptor)) {
+ std::cerr << "Could not find file in descriptor database: " << input_file
+ << ": " << strerror(ENOENT) << std::endl;
+ return false;
+ }
+
+ // Enforce --disallow_services.
+ if (disallow_services_ && file_descriptor.service_size() > 0) {
+ std::cerr << file_descriptor.name()
+ << ": This file contains services, but "
+ "--disallow_services was used."
+ << std::endl;
+ return false;
+ }
+
+ }
+ return true;
+}
+
+bool CommandLineInterface::ParseInputFiles(
+ DescriptorPool* descriptor_pool, DiskSourceTree* source_tree,
+ std::vector<const FileDescriptor*>* parsed_files) {
+
+ if (!proto_path_.empty()) {
+ // Track unused imports in all source files that were loaded from the
+ // filesystem. We do not track unused imports for files loaded from
+ // descriptor sets as they may be programmatically generated in which case
+ // exerting this level of rigor is less desirable. We're also making the
+ // assumption that the initial parse of the proto from the filesystem
+ // was rigorous in checking unused imports and that the descriptor set
+ // being parsed was produced then and that it was subsequent mutations
+ // of that descriptor set that left unused imports.
+ //
+ // Note that relying on proto_path exclusively is limited in that we may
+ // be loading descriptors from both the filesystem and descriptor sets
+ // depending on the invocation. At least for invocations that are
+ // exclusively reading from descriptor sets, we can eliminate this failure
+ // condition.
+ for (const auto& input_file : input_files_) {
+ descriptor_pool->AddUnusedImportTrackFile(input_file);
+ }
+ }
+
+ bool result = true;
+ // Parse each file.
+ for (const auto& input_file : input_files_) {
+ // Import the file.
+ const FileDescriptor* parsed_file =
+ descriptor_pool->FindFileByName(input_file);
+ if (parsed_file == NULL) {
+ result = false;
+ break;
+ }
+ parsed_files->push_back(parsed_file);
+
+ // Enforce --disallow_services.
+ if (disallow_services_ && parsed_file->service_count() > 0) {
+ std::cerr << parsed_file->name()
+ << ": This file contains services, but "
+ "--disallow_services was used."
+ << std::endl;
+ result = false;
+ break;
+ }
+
+
+ // Enforce --direct_dependencies
+ if (direct_dependencies_explicitly_set_) {
+ bool indirect_imports = false;
+ for (int i = 0; i < parsed_file->dependency_count(); i++) {
+ if (direct_dependencies_.find(parsed_file->dependency(i)->name()) ==
+ direct_dependencies_.end()) {
+ indirect_imports = true;
+ std::cerr << parsed_file->name() << ": "
+ << StringReplace(direct_dependencies_violation_msg_, "%s",
+ parsed_file->dependency(i)->name(),
+ true /* replace_all */)
+ << std::endl;
+ }
+ }
+ if (indirect_imports) {
+ result = false;
+ break;
+ }
+ }
+ }
+ descriptor_pool->ClearUnusedImportTrackFiles();
+ return result;
+}
+
+void CommandLineInterface::Clear() {
+ // Clear all members that are set by Run(). Note that we must not clear
+ // members which are set by other methods before Run() is called.
+ executable_name_.clear();
+ proto_path_.clear();
+ input_files_.clear();
+ direct_dependencies_.clear();
+ direct_dependencies_violation_msg_ = kDefaultDirectDependenciesViolationMsg;
+ output_directives_.clear();
+ codec_type_.clear();
+ descriptor_set_in_names_.clear();
+ descriptor_set_out_name_.clear();
+ dependency_out_name_.clear();
+
+
+ mode_ = MODE_COMPILE;
+ print_mode_ = PRINT_NONE;
+ imports_in_descriptor_set_ = false;
+ source_info_in_descriptor_set_ = false;
+ disallow_services_ = false;
+ direct_dependencies_explicitly_set_ = false;
+ deterministic_output_ = false;
+}
+
+bool CommandLineInterface::MakeProtoProtoPathRelative(
+ DiskSourceTree* source_tree, std::string* proto,
+ DescriptorDatabase* fallback_database) {
+ // If it's in the fallback db, don't report non-existent file errors.
+ FileDescriptorProto fallback_file;
+ bool in_fallback_database =
+ fallback_database != nullptr &&
+ fallback_database->FindFileByName(*proto, &fallback_file);
+
+ // If the input file path is not a physical file path, it must be a virtual
+ // path.
+ if (access(proto->c_str(), F_OK) < 0) {
+ std::string disk_file;
+ if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) ||
+ in_fallback_database) {
+ return true;
+ } else {
+ std::cerr << "Could not make proto path relative: " << *proto << ": "
+ << strerror(ENOENT) << std::endl;
+ return false;
+ }
+ }
+
+ std::string virtual_file, shadowing_disk_file;
+ switch (source_tree->DiskFileToVirtualFile(*proto, &virtual_file,
+ &shadowing_disk_file)) {
+ case DiskSourceTree::SUCCESS:
+ *proto = virtual_file;
+ break;
+ case DiskSourceTree::SHADOWED:
+ std::cerr << *proto << ": Input is shadowed in the --proto_path by \""
+ << shadowing_disk_file
+ << "\". Either use the latter file as your input or reorder "
+ "the --proto_path so that the former file's location "
+ "comes first."
+ << std::endl;
+ return false;
+ case DiskSourceTree::CANNOT_OPEN: {
+ if (in_fallback_database) {
+ return true;
+ }
+ std::string error_str = source_tree->GetLastErrorMessage().empty()
+ ? strerror(errno)
+ : source_tree->GetLastErrorMessage();
+ std::cerr << "Could not map to virtual file: " << *proto << ": "
+ << error_str << std::endl;
+ return false;
+ }
+ case DiskSourceTree::NO_MAPPING: {
+ // Try to interpret the path as a virtual path.
+ std::string disk_file;
+ if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) ||
+ in_fallback_database) {
+ return true;
+ } else {
+ // The input file path can't be mapped to any --proto_path and it also
+ // can't be interpreted as a virtual path.
+ std::cerr
+ << *proto
+ << ": File does not reside within any path "
+ "specified using --proto_path (or -I). You must specify a "
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think)."
+ << std::endl;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool CommandLineInterface::MakeInputsBeProtoPathRelative(
+ DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) {
+ for (auto& input_file : input_files_) {
+ if (!MakeProtoProtoPathRelative(source_tree, &input_file,
+ fallback_database)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool CommandLineInterface::ExpandArgumentFile(
+ const std::string& file, std::vector<std::string>* arguments) {
+ // The argument file is searched in the working directory only. We don't
+ // use the proto import path here.
+ std::ifstream file_stream(file.c_str());
+ if (!file_stream.is_open()) {
+ return false;
+ }
+ std::string argument;
+ // We don't support any kind of shell expansion right now.
+ while (std::getline(file_stream, argument)) {
+ arguments->push_back(argument);
+ }
+ return true;
+}
+
+CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments(
+ int argc, const char* const argv[]) {
+ executable_name_ = argv[0];
+
+ std::vector<std::string> arguments;
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] == '@') {
+ if (!ExpandArgumentFile(argv[i] + 1, &arguments)) {
+ std::cerr << "Failed to open argument file: " << (argv[i] + 1)
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ continue;
+ }
+ arguments.push_back(argv[i]);
+ }
+
+ // if no arguments are given, show help
+ if (arguments.empty()) {
+ PrintHelpText();
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
+ }
+
+ // Iterate through all arguments and parse them.
+ for (int i = 0; i < arguments.size(); ++i) {
+ std::string name, value;
+
+ if (ParseArgument(arguments[i].c_str(), &name, &value)) {
+ // Returned true => Use the next argument as the flag value.
+ if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') {
+ std::cerr << "Missing value for flag: " << name << std::endl;
+ if (name == "--decode") {
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
+ }
+ return PARSE_ARGUMENT_FAIL;
+ } else {
+ ++i;
+ value = arguments[i];
+ }
+ }
+
+ ParseArgumentStatus status = InterpretArgument(name, value);
+ if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) return status;
+ }
+
+ // Make sure each plugin option has a matching plugin output.
+ bool foundUnknownPluginOption = false;
+ for (std::map<std::string, std::string>::const_iterator i =
+ plugin_parameters_.begin();
+ i != plugin_parameters_.end(); ++i) {
+ if (plugins_.find(i->first) != plugins_.end()) {
+ continue;
+ }
+ bool foundImplicitPlugin = false;
+ for (std::vector<OutputDirective>::const_iterator j =
+ output_directives_.begin();
+ j != output_directives_.end(); ++j) {
+ if (j->generator == NULL) {
+ std::string plugin_name = PluginName(plugin_prefix_, j->name);
+ if (plugin_name == i->first) {
+ foundImplicitPlugin = true;
+ break;
+ }
+ }
+ }
+ if (!foundImplicitPlugin) {
+ std::cerr << "Unknown flag: "
+ // strip prefix + "gen-" and add back "_opt"
+ << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt"
+ << std::endl;
+ foundUnknownPluginOption = true;
+ }
+ }
+ if (foundUnknownPluginOption) {
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ // The --proto_path & --descriptor_set_in flags both specify places to look
+ // for proto files. If neither were given, use the current working directory.
+ if (proto_path_.empty() && descriptor_set_in_names_.empty()) {
+ // Don't use make_pair as the old/default standard library on Solaris
+ // doesn't support it without explicit template parameters, which are
+ // incompatible with C++0x's make_pair.
+ proto_path_.push_back(std::pair<std::string, std::string>("", "."));
+ }
+
+ // Check error cases that span multiple flag values.
+ bool missing_proto_definitions = false;
+ switch (mode_) {
+ case MODE_COMPILE:
+ missing_proto_definitions = input_files_.empty();
+ break;
+ case MODE_DECODE:
+ // Handle --decode_raw separately, since it requires that no proto
+ // definitions are specified.
+ if (codec_type_.empty()) {
+ if (!input_files_.empty() || !descriptor_set_in_names_.empty()) {
+ std::cerr
+ << "When using --decode_raw, no input files should be given."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ missing_proto_definitions = false;
+ break; // only for --decode_raw
+ }
+ // --decode (not raw) is handled the same way as the rest of the modes.
+ PROTOBUF_FALLTHROUGH_INTENDED;
+ case MODE_ENCODE:
+ case MODE_PRINT:
+ missing_proto_definitions =
+ input_files_.empty() && descriptor_set_in_names_.empty();
+ break;
+ default:
+ GOOGLE_LOG(FATAL) << "Unexpected mode: " << mode_;
+ }
+ if (missing_proto_definitions) {
+ std::cerr << "Missing input file." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ == MODE_COMPILE && output_directives_.empty() &&
+ descriptor_set_out_name_.empty()) {
+ std::cerr << "Missing output directives." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
+ std::cerr << "Can only use --dependency_out=FILE when generating code."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ != MODE_ENCODE && deterministic_output_) {
+ std::cerr << "Can only use --deterministic_output with --encode."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!dependency_out_name_.empty() && input_files_.size() > 1) {
+ std::cerr
+ << "Can only process one input file when using --dependency_out=FILE."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (imports_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
+ std::cerr << "--include_imports only makes sense when combined with "
+ "--descriptor_set_out."
+ << std::endl;
+ }
+ if (source_info_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
+ std::cerr << "--include_source_info only makes sense when combined with "
+ "--descriptor_set_out."
+ << std::endl;
+ }
+
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE;
+}
+
+bool CommandLineInterface::ParseArgument(const char* arg, std::string* name,
+ std::string* value) {
+ bool parsed_value = false;
+
+ if (arg[0] != '-') {
+ // Not a flag.
+ name->clear();
+ parsed_value = true;
+ *value = arg;
+ } else if (arg[1] == '-') {
+ // Two dashes: Multi-character name, with '=' separating name and
+ // value.
+ const char* equals_pos = strchr(arg, '=');
+ if (equals_pos != NULL) {
+ *name = std::string(arg, equals_pos - arg);
+ *value = equals_pos + 1;
+ parsed_value = true;
+ } else {
+ *name = arg;
+ }
+ } else {
+ // One dash: One-character name, all subsequent characters are the
+ // value.
+ if (arg[1] == '\0') {
+ // arg is just "-". We treat this as an input file, except that at
+ // present this will just lead to a "file not found" error.
+ name->clear();
+ *value = arg;
+ parsed_value = true;
+ } else {
+ *name = std::string(arg, 2);
+ *value = arg + 2;
+ parsed_value = !value->empty();
+ }
+ }
+
+ // Need to return true iff the next arg should be used as the value for this
+ // one, false otherwise.
+
+ if (parsed_value) {
+ // We already parsed a value for this flag.
+ return false;
+ }
+
+ if (*name == "-h" || *name == "--help" || *name == "--disallow_services" ||
+ *name == "--include_imports" || *name == "--include_source_info" ||
+ *name == "--version" || *name == "--decode_raw" ||
+ *name == "--print_free_field_numbers" ||
+ *name == "--experimental_allow_proto3_optional" ||
+ *name == "--deterministic_output" || *name == "--fatal_warnings") {
+ // HACK: These are the only flags that don't take a value.
+ // They probably should not be hard-coded like this but for now it's
+ // not worth doing better.
+ return false;
+ }
+
+ // Next argument is the flag value.
+ return true;
+}
+
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::InterpretArgument(const std::string& name,
+ const std::string& value) {
+ if (name.empty()) {
+ // Not a flag. Just a filename.
+ if (value.empty()) {
+ std::cerr
+ << "You seem to have passed an empty string as one of the "
+ "arguments to "
+ << executable_name_
+ << ". This is actually "
+ "sort of hard to do. Congrats. Unfortunately it is not valid "
+ "input so the program is going to die now."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+#if defined(_WIN32)
+ // On Windows, the shell (typically cmd.exe) does not expand wildcards in
+ // file names (e.g. foo\*.proto), so we do it ourselves.
+ switch (google::protobuf::io::win32::ExpandWildcards(
+ value,
+ [this](const string& path) { this->input_files_.push_back(path); })) {
+ case google::protobuf::io::win32::ExpandWildcardsResult::kSuccess:
+ break;
+ case google::protobuf::io::win32::ExpandWildcardsResult::
+ kErrorNoMatchingFile:
+ // Path does not exist, is not a file, or it's longer than MAX_PATH and
+ // long path handling is disabled.
+ std::cerr << "Invalid file name pattern or missing input file \""
+ << value << "\"" << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ default:
+ std::cerr << "Cannot convert path \"" << value
+ << "\" to or from Windows style" << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+#else // not _WIN32
+ // On other platforms than Windows (e.g. Linux, Mac OS) the shell (typically
+ // Bash) expands wildcards.
+ input_files_.push_back(value);
+#endif // _WIN32
+
+ } else if (name == "-I" || name == "--proto_path") {
+ // Java's -classpath (and some other languages) delimits path components
+ // with colons. Let's accept that syntax too just to make things more
+ // intuitive.
+ std::vector<std::string> parts = Split(
+ value, CommandLineInterface::kPathSeparator,
+ true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ std::string virtual_path;
+ std::string disk_path;
+
+ std::string::size_type equals_pos = parts[i].find_first_of('=');
+ if (equals_pos == std::string::npos) {
+ virtual_path = "";
+ disk_path = parts[i];
+ } else {
+ virtual_path = parts[i].substr(0, equals_pos);
+ disk_path = parts[i].substr(equals_pos + 1);
+ }
+
+ if (disk_path.empty()) {
+ std::cerr
+ << "--proto_path passed empty directory name. (Use \".\" for "
+ "current directory.)"
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ // Make sure disk path exists, warn otherwise.
+ if (access(disk_path.c_str(), F_OK) < 0) {
+ // Try the original path; it may have just happened to have a '=' in it.
+ if (access(parts[i].c_str(), F_OK) < 0) {
+ std::cerr << disk_path << ": warning: directory does not exist."
+ << std::endl;
+ } else {
+ virtual_path = "";
+ disk_path = parts[i];
+ }
+ }
+
+ // Don't use make_pair as the old/default standard library on Solaris
+ // doesn't support it without explicit template parameters, which are
+ // incompatible with C++0x's make_pair.
+ proto_path_.push_back(
+ std::pair<std::string, std::string>(virtual_path, disk_path));
+ }
+
+ } else if (name == "--direct_dependencies") {
+ if (direct_dependencies_explicitly_set_) {
+ std::cerr << name
+ << " may only be passed once. To specify multiple "
+ "direct dependencies, pass them all as a single "
+ "parameter separated by ':'."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ direct_dependencies_explicitly_set_ = true;
+ std::vector<std::string> direct =
+ Split(value, ":", true);
+ GOOGLE_DCHECK(direct_dependencies_.empty());
+ direct_dependencies_.insert(direct.begin(), direct.end());
+
+ } else if (name == "--direct_dependencies_violation_msg") {
+ direct_dependencies_violation_msg_ = value;
+
+ } else if (name == "--descriptor_set_in") {
+ if (!descriptor_set_in_names_.empty()) {
+ std::cerr << name
+ << " may only be passed once. To specify multiple "
+ "descriptor sets, pass them all as a single "
+ "parameter separated by '"
+ << CommandLineInterface::kPathSeparator << "'." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (value.empty()) {
+ std::cerr << name << " requires a non-empty value." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!dependency_out_name_.empty()) {
+ std::cerr << name << " cannot be used with --dependency_out."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ descriptor_set_in_names_ = Split(
+ value, CommandLineInterface::kPathSeparator,
+ true);
+
+ } else if (name == "-o" || name == "--descriptor_set_out") {
+ if (!descriptor_set_out_name_.empty()) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (value.empty()) {
+ std::cerr << name << " requires a non-empty value." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ != MODE_COMPILE) {
+ std::cerr
+ << "Cannot use --encode or --decode and generate descriptors at the "
+ "same time."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ descriptor_set_out_name_ = value;
+
+ } else if (name == "--dependency_out") {
+ if (!dependency_out_name_.empty()) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (value.empty()) {
+ std::cerr << name << " requires a non-empty value." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!descriptor_set_in_names_.empty()) {
+ std::cerr << name << " cannot be used with --descriptor_set_in."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ dependency_out_name_ = value;
+
+ } else if (name == "--include_imports") {
+ if (imports_in_descriptor_set_) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ imports_in_descriptor_set_ = true;
+
+ } else if (name == "--include_source_info") {
+ if (source_info_in_descriptor_set_) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ source_info_in_descriptor_set_ = true;
+
+ } else if (name == "-h" || name == "--help") {
+ PrintHelpText();
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
+
+ } else if (name == "--version") {
+ if (!version_info_.empty()) {
+ std::cout << version_info_ << std::endl;
+ }
+ std::cout << "libprotoc " << internal::VersionString(PROTOBUF_VERSION)
+ << PROTOBUF_VERSION_SUFFIX << std::endl;
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
+
+ } else if (name == "--disallow_services") {
+ disallow_services_ = true;
+
+
+ } else if (name == "--experimental_allow_proto3_optional") {
+ // Flag is no longer observed, but we allow it for backward compat.
+ } else if (name == "--encode" || name == "--decode" ||
+ name == "--decode_raw") {
+ if (mode_ != MODE_COMPILE) {
+ std::cerr << "Only one of --encode and --decode can be specified."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
+
+ if (value.empty() && name != "--decode_raw") {
+ std::cerr << "Type name for " << name << " cannot be blank." << std::endl;
+ if (name == "--decode") {
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
+ }
+ return PARSE_ARGUMENT_FAIL;
+ } else if (!value.empty() && name == "--decode_raw") {
+ std::cerr << "--decode_raw does not take a parameter." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ codec_type_ = value;
+
+ } else if (name == "--deterministic_output") {
+ deterministic_output_ = true;
+
+ } else if (name == "--error_format") {
+ if (value == "gcc") {
+ error_format_ = ERROR_FORMAT_GCC;
+ } else if (value == "msvs") {
+ error_format_ = ERROR_FORMAT_MSVS;
+ } else {
+ std::cerr << "Unknown error format: " << value << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ } else if (name == "--fatal_warnings") {
+ if (fatal_warnings_) {
+ std::cerr << name << " may only be passed once." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ fatal_warnings_ = true;
+ } else if (name == "--plugin") {
+ if (plugin_prefix_.empty()) {
+ std::cerr << "This compiler does not support plugins." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ std::string plugin_name;
+ std::string path;
+
+ std::string::size_type equals_pos = value.find_first_of('=');
+ if (equals_pos == std::string::npos) {
+ // Use the basename of the file.
+ std::string::size_type slash_pos = value.find_last_of('/');
+ if (slash_pos == std::string::npos) {
+ plugin_name = value;
+ } else {
+ plugin_name = value.substr(slash_pos + 1);
+ }
+ path = value;
+ } else {
+ plugin_name = value.substr(0, equals_pos);
+ path = value.substr(equals_pos + 1);
+ }
+
+ plugins_[plugin_name] = path;
+
+ } else if (name == "--print_free_field_numbers") {
+ if (mode_ != MODE_COMPILE) {
+ std::cerr << "Cannot use " << name
+ << " and use --encode, --decode or print "
+ << "other info at the same time." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ mode_ = MODE_PRINT;
+ print_mode_ = PRINT_FREE_FIELDS;
+ } else {
+ // Some other flag. Look it up in the generators list.
+ const GeneratorInfo* generator_info =
+ FindOrNull(generators_by_flag_name_, name);
+ if (generator_info == NULL &&
+ (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
+ // Check if it's a generator option flag.
+ generator_info = FindOrNull(generators_by_option_name_, name);
+ if (generator_info != NULL) {
+ std::string* parameters =
+ &generator_parameters_[generator_info->flag_name];
+ if (!parameters->empty()) {
+ parameters->append(",");
+ }
+ parameters->append(value);
+ } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) {
+ std::string* parameters =
+ &plugin_parameters_[PluginName(plugin_prefix_, name)];
+ if (!parameters->empty()) {
+ parameters->append(",");
+ }
+ parameters->append(value);
+ } else {
+ std::cerr << "Unknown flag: " << name << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ } else {
+ // It's an output flag. Add it to the output directives.
+ if (mode_ != MODE_COMPILE) {
+ std::cerr << "Cannot use --encode, --decode or print .proto info and "
+ "generate code at the same time."
+ << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ OutputDirective directive;
+ directive.name = name;
+ if (generator_info == NULL) {
+ directive.generator = NULL;
+ } else {
+ directive.generator = generator_info->generator;
+ }
+
+ // Split value at ':' to separate the generator parameter from the
+ // filename. However, avoid doing this if the colon is part of a valid
+ // Windows-style absolute path.
+ std::string::size_type colon_pos = value.find_first_of(':');
+ if (colon_pos == std::string::npos || IsWindowsAbsolutePath(value)) {
+ directive.output_location = value;
+ } else {
+ directive.parameter = value.substr(0, colon_pos);
+ directive.output_location = value.substr(colon_pos + 1);
+ }
+
+ output_directives_.push_back(directive);
+ }
+ }
+
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE;
+}
+
+void CommandLineInterface::PrintHelpText() {
+ // Sorry for indentation here; line wrapping would be uglier.
+ std::cout << "Usage: " << executable_name_ << " [OPTION] PROTO_FILES";
+ std::cout << R"(
+Parse PROTO_FILES and generate output based on the options given:
+ -IPATH, --proto_path=PATH Specify the directory in which to search for
+ imports. May be specified multiple times;
+ directories will be searched in order. If not
+ given, the current working directory is used.
+ If not found in any of the these directories,
+ the --descriptor_set_in descriptors will be
+ checked for required proto file.
+ --version Show version info and exit.
+ -h, --help Show this text and exit.
+ --encode=MESSAGE_TYPE Read a text-format message of the given type
+ from standard input and write it in binary
+ to standard output. The message type must
+ be defined in PROTO_FILES or their imports.
+ --deterministic_output When using --encode, ensure map fields are
+ deterministically ordered. Note that this order
+ is not canonical, and changes across builds or
+ releases of protoc.
+ --decode=MESSAGE_TYPE Read a binary message of the given type from
+ standard input and write it in text format
+ to standard output. The message type must
+ be defined in PROTO_FILES or their imports.
+ --decode_raw Read an arbitrary protocol message from
+ standard input and write the raw tag/value
+ pairs in text format to standard output. No
+ PROTO_FILES should be given when using this
+ flag.
+ --descriptor_set_in=FILES Specifies a delimited list of FILES
+ each containing a FileDescriptorSet (a
+ protocol buffer defined in descriptor.proto).
+ The FileDescriptor for each of the PROTO_FILES
+ provided will be loaded from these
+ FileDescriptorSets. If a FileDescriptor
+ appears multiple times, the first occurrence
+ will be used.
+ -oFILE, Writes a FileDescriptorSet (a protocol buffer,
+ --descriptor_set_out=FILE defined in descriptor.proto) containing all of
+ the input files to FILE.
+ --include_imports When using --descriptor_set_out, also include
+ all dependencies of the input files in the
+ set, so that the set is self-contained.
+ --include_source_info When using --descriptor_set_out, do not strip
+ SourceCodeInfo from the FileDescriptorProto.
+ This results in vastly larger descriptors that
+ include information about the original
+ location of each decl in the source file as
+ well as surrounding comments.
+ --dependency_out=FILE Write a dependency output file in the format
+ expected by make. This writes the transitive
+ set of input file paths to FILE
+ --error_format=FORMAT Set the format in which to print errors.
+ FORMAT may be 'gcc' (the default) or 'msvs'
+ (Microsoft Visual Studio format).
+ --fatal_warnings Make warnings be fatal (similar to -Werr in
+ gcc). This flag will make protoc return
+ with a non-zero exit code if any warnings
+ are generated.
+ --print_free_field_numbers Print the free field numbers of the messages
+ defined in the given proto files. Groups share
+ the same field number space with the parent
+ message. Extension ranges are counted as
+ occupied fields numbers.)";
+ if (!plugin_prefix_.empty()) {
+ std::cout << R"(
+ --plugin=EXECUTABLE Specifies a plugin executable to use.
+ Normally, protoc searches the PATH for
+ plugins, but you may specify additional
+ executables not in the path using this flag.
+ Additionally, EXECUTABLE may be of the form
+ NAME=PATH, in which case the given plugin name
+ is mapped to the given executable even if
+ the executable's own name differs.)";
+ }
+
+ for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
+ iter != generators_by_flag_name_.end(); ++iter) {
+ // FIXME(kenton): If the text is long enough it will wrap, which is ugly,
+ // but fixing this nicely (e.g. splitting on spaces) is probably more
+ // trouble than it's worth.
+ std::cout << std::endl
+ << " " << iter->first << "=OUT_DIR "
+ << std::string(19 - iter->first.size(),
+ ' ') // Spaces for alignment.
+ << iter->second.help_text;
+ }
+ std::cout << R"(
+ @<filename> Read options and filenames from file. If a
+ relative file path is specified, the file
+ will be searched in the working directory.
+ The --proto_path option will not affect how
+ this argument file is searched. Content of
+ the file will be expanded in the position of
+ @<filename> as in the argument list. Note
+ that shell expansion is not applied to the
+ content of the file (i.e., you cannot use
+ quotes, wildcards, escapes, commands, etc.).
+ Each line corresponds to a single argument,
+ even if it contains spaces.)";
+ std::cout << std::endl;
+}
+
+bool CommandLineInterface::EnforceProto3OptionalSupport(
+ const std::string& codegen_name, uint64_t supported_features,
+ const std::vector<const FileDescriptor*>& parsed_files) const {
+ bool supports_proto3_optional =
+ supported_features & CodeGenerator::FEATURE_PROTO3_OPTIONAL;
+ if (!supports_proto3_optional) {
+ for (const auto fd : parsed_files) {
+ if (ContainsProto3Optional(fd)) {
+ std::cerr << fd->name()
+ << ": is a proto3 file that contains optional fields, but "
+ "code generator "
+ << codegen_name
+ << " hasn't been updated to support optional fields in "
+ "proto3. Please ask the owner of this code generator to "
+ "support proto3 optional.";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool CommandLineInterface::GenerateOutput(
+ const std::vector<const FileDescriptor*>& parsed_files,
+ const OutputDirective& output_directive,
+ GeneratorContext* generator_context) {
+ // Call the generator.
+ std::string error;
+ if (output_directive.generator == NULL) {
+ // This is a plugin.
+ GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") &&
+ HasSuffixString(output_directive.name, "_out"))
+ << "Bad name for plugin generator: " << output_directive.name;
+
+ std::string plugin_name = PluginName(plugin_prefix_, output_directive.name);
+ std::string parameters = output_directive.parameter;
+ if (!plugin_parameters_[plugin_name].empty()) {
+ if (!parameters.empty()) {
+ parameters.append(",");
+ }
+ parameters.append(plugin_parameters_[plugin_name]);
+ }
+ if (!GeneratePluginOutput(parsed_files, plugin_name, parameters,
+ generator_context, &error)) {
+ std::cerr << output_directive.name << ": " << error << std::endl;
+ return false;
+ }
+ } else {
+ // Regular generator.
+ std::string parameters = output_directive.parameter;
+ if (!generator_parameters_[output_directive.name].empty()) {
+ if (!parameters.empty()) {
+ parameters.append(",");
+ }
+ parameters.append(generator_parameters_[output_directive.name]);
+ }
+ if (!EnforceProto3OptionalSupport(
+ output_directive.name,
+ output_directive.generator->GetSupportedFeatures(), parsed_files)) {
+ return false;
+ }
+
+ if (!output_directive.generator->GenerateAll(parsed_files, parameters,
+ generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": " << error << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::GenerateDependencyManifestFile(
+ const std::vector<const FileDescriptor*>& parsed_files,
+ const GeneratorContextMap& output_directories,
+ DiskSourceTree* source_tree) {
+ FileDescriptorSet file_set;
+
+ std::set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(parsed_files[i], false, false, &already_seen,
+ file_set.mutable_file());
+ }
+
+ std::vector<std::string> output_filenames;
+ for (const auto& pair : output_directories) {
+ const std::string& location = pair.first;
+ GeneratorContextImpl* directory = pair.second.get();
+ std::vector<std::string> relative_output_filenames;
+ directory->GetOutputFilenames(&relative_output_filenames);
+ for (int i = 0; i < relative_output_filenames.size(); i++) {
+ std::string output_filename = location + relative_output_filenames[i];
+ if (output_filename.compare(0, 2, "./") == 0) {
+ output_filename = output_filename.substr(2);
+ }
+ output_filenames.push_back(output_filename);
+ }
+ }
+
+ int fd;
+ do {
+ fd = open(dependency_out_name_.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (fd < 0 && errno == EINTR);
+
+ if (fd < 0) {
+ perror(dependency_out_name_.c_str());
+ return false;
+ }
+
+ io::FileOutputStream out(fd);
+ io::Printer printer(&out, '$');
+
+ for (int i = 0; i < output_filenames.size(); i++) {
+ printer.Print(output_filenames[i].c_str());
+ if (i == output_filenames.size() - 1) {
+ printer.Print(":");
+ } else {
+ printer.Print(" \\\n");
+ }
+ }
+
+ for (int i = 0; i < file_set.file_size(); i++) {
+ const FileDescriptorProto& file = file_set.file(i);
+ const std::string& virtual_file = file.name();
+ std::string disk_file;
+ if (source_tree &&
+ source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) {
+ printer.Print(" $disk_file$", "disk_file", disk_file);
+ if (i < file_set.file_size() - 1) printer.Print("\\\n");
+ } else {
+ std::cerr << "Unable to identify path for file " << virtual_file
+ << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::GeneratePluginOutput(
+ const std::vector<const FileDescriptor*>& parsed_files,
+ const std::string& plugin_name, const std::string& parameter,
+ GeneratorContext* generator_context, std::string* error) {
+ CodeGeneratorRequest request;
+ CodeGeneratorResponse response;
+ std::string processed_parameter = parameter;
+
+
+ // Build the request.
+ if (!processed_parameter.empty()) {
+ request.set_parameter(processed_parameter);
+ }
+
+
+ std::set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ request.add_file_to_generate(parsed_files[i]->name());
+ GetTransitiveDependencies(parsed_files[i],
+ true, // Include json_name for plugins.
+ true, // Include source code info.
+ &already_seen, request.mutable_proto_file());
+ }
+
+ google::protobuf::compiler::Version* version =
+ request.mutable_compiler_version();
+ version->set_major(PROTOBUF_VERSION / 1000000);
+ version->set_minor(PROTOBUF_VERSION / 1000 % 1000);
+ version->set_patch(PROTOBUF_VERSION % 1000);
+ version->set_suffix(PROTOBUF_VERSION_SUFFIX);
+
+ // Invoke the plugin.
+ Subprocess subprocess;
+
+ if (plugins_.count(plugin_name) > 0) {
+ subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME);
+ } else {
+ subprocess.Start(plugin_name, Subprocess::SEARCH_PATH);
+ }
+
+ std::string communicate_error;
+ if (!subprocess.Communicate(request, &response, &communicate_error)) {
+ *error = strings::Substitute("$0: $1", plugin_name, communicate_error);
+ return false;
+ }
+
+ // Write the files. We do this even if there was a generator error in order
+ // to match the behavior of a compiled-in generator.
+ std::unique_ptr<io::ZeroCopyOutputStream> current_output;
+ for (int i = 0; i < response.file_size(); i++) {
+ const CodeGeneratorResponse::File& output_file = response.file(i);
+
+ if (!output_file.insertion_point().empty()) {
+ std::string filename = output_file.name();
+ // Open a file for insert.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(
+ generator_context->OpenForInsertWithGeneratedCodeInfo(
+ filename, output_file.insertion_point(),
+ output_file.generated_code_info()));
+ } else if (!output_file.name().empty()) {
+ // Starting a new file. Open it.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(generator_context->Open(output_file.name()));
+ } else if (current_output == NULL) {
+ *error = strings::Substitute(
+ "$0: First file chunk returned by plugin did not specify a file "
+ "name.",
+ plugin_name);
+ return false;
+ }
+
+ // Use CodedOutputStream for convenience; otherwise we'd need to provide
+ // our own buffer-copying loop.
+ io::CodedOutputStream writer(current_output.get());
+ writer.WriteString(output_file.content());
+ }
+
+ // Check for errors.
+ if (!response.error().empty()) {
+ // Generator returned an error.
+ *error = response.error();
+ return false;
+ } else if (!EnforceProto3OptionalSupport(
+ plugin_name, response.supported_features(), parsed_files)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
+ // Look up the type.
+ const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
+ if (type == NULL) {
+ std::cerr << "Type not defined: " << codec_type_ << std::endl;
+ return false;
+ }
+
+ DynamicMessageFactory dynamic_factory(pool);
+ std::unique_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
+
+ if (mode_ == MODE_ENCODE) {
+ SetFdToTextMode(STDIN_FILENO);
+ SetFdToBinaryMode(STDOUT_FILENO);
+ } else {
+ SetFdToBinaryMode(STDIN_FILENO);
+ SetFdToTextMode(STDOUT_FILENO);
+ }
+
+ io::FileInputStream in(STDIN_FILENO);
+ io::FileOutputStream out(STDOUT_FILENO);
+
+ if (mode_ == MODE_ENCODE) {
+ // Input is text.
+ ErrorPrinter error_collector(error_format_);
+ TextFormat::Parser parser;
+ parser.RecordErrorsTo(&error_collector);
+ parser.AllowPartialMessage(true);
+
+ if (!parser.Parse(&in, message.get())) {
+ std::cerr << "Failed to parse input." << std::endl;
+ return false;
+ }
+ } else {
+ // Input is binary.
+ if (!message->ParsePartialFromZeroCopyStream(&in)) {
+ std::cerr << "Failed to parse input." << std::endl;
+ return false;
+ }
+ }
+
+ if (!message->IsInitialized()) {
+ std::cerr << "warning: Input message is missing required fields: "
+ << message->InitializationErrorString() << std::endl;
+ }
+
+ if (mode_ == MODE_ENCODE) {
+ // Output is binary.
+ io::CodedOutputStream coded_out(&out);
+ coded_out.SetSerializationDeterministic(deterministic_output_);
+ if (!message->SerializePartialToCodedStream(&coded_out)) {
+ std::cerr << "output: I/O error." << std::endl;
+ return false;
+ }
+ } else {
+ // Output is text.
+ if (!TextFormat::Print(*message, &out)) {
+ std::cerr << "output: I/O error." << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CommandLineInterface::WriteDescriptorSet(
+ const std::vector<const FileDescriptor*>& parsed_files) {
+ FileDescriptorSet file_set;
+
+ std::set<const FileDescriptor*> already_seen;
+ if (!imports_in_descriptor_set_) {
+ // Since we don't want to output transitive dependencies, but we do want
+ // things to be in dependency order, add all dependencies that aren't in
+ // parsed_files to already_seen. This will short circuit the recursion
+ // in GetTransitiveDependencies.
+ std::set<const FileDescriptor*> to_output;
+ to_output.insert(parsed_files.begin(), parsed_files.end());
+ for (int i = 0; i < parsed_files.size(); i++) {
+ const FileDescriptor* file = parsed_files[i];
+ for (int j = 0; j < file->dependency_count(); j++) {
+ const FileDescriptor* dependency = file->dependency(j);
+ // if the dependency isn't in parsed files, mark it as already seen
+ if (to_output.find(dependency) == to_output.end()) {
+ already_seen.insert(dependency);
+ }
+ }
+ }
+ }
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(parsed_files[i],
+ true, // Include json_name
+ source_info_in_descriptor_set_, &already_seen,
+ file_set.mutable_file());
+ }
+
+ int fd;
+ do {
+ fd = open(descriptor_set_out_name_.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (fd < 0 && errno == EINTR);
+
+ if (fd < 0) {
+ perror(descriptor_set_out_name_.c_str());
+ return false;
+ }
+
+ io::FileOutputStream out(fd);
+
+ {
+ io::CodedOutputStream coded_out(&out);
+ // Determinism is useful here because build outputs are sometimes checked
+ // into version control.
+ coded_out.SetSerializationDeterministic(true);
+ if (!file_set.SerializeToCodedStream(&coded_out)) {
+ std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
+ out.Close();
+ return false;
+ }
+ }
+
+ if (!out.Close()) {
+ std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+void CommandLineInterface::GetTransitiveDependencies(
+ const FileDescriptor* file, bool include_json_name,
+ bool include_source_code_info,
+ std::set<const FileDescriptor*>* already_seen,
+ RepeatedPtrField<FileDescriptorProto>* output) {
+ if (!already_seen->insert(file).second) {
+ // Already saw this file. Skip.
+ return;
+ }
+
+ // Add all dependencies.
+ for (int i = 0; i < file->dependency_count(); i++) {
+ GetTransitiveDependencies(file->dependency(i), include_json_name,
+ include_source_code_info, already_seen, output);
+ }
+
+ // Add this file.
+ FileDescriptorProto* new_descriptor = output->Add();
+ file->CopyTo(new_descriptor);
+ if (include_json_name) {
+ file->CopyJsonNameTo(new_descriptor);
+ }
+ if (include_source_code_info) {
+ file->CopySourceCodeInfoTo(new_descriptor);
+ }
+}
+
+namespace {
+
+// Utility function for PrintFreeFieldNumbers.
+// Stores occupied ranges into the ranges parameter, and next level of sub
+// message types into the nested_messages parameter. The FieldRange is left
+// inclusive, right exclusive. i.e. [a, b).
+//
+// Nested Messages:
+// Note that it only stores the nested message type, iff the nested type is
+// either a direct child of the given descriptor, or the nested type is a
+// descendant of the given descriptor and all the nodes between the
+// nested type and the given descriptor are group types. e.g.
+//
+// message Foo {
+// message Bar {
+// message NestedBar {}
+// }
+// group Baz = 1 {
+// group NestedBazGroup = 2 {
+// message Quz {
+// message NestedQuz {}
+// }
+// }
+// message NestedBaz {}
+// }
+// }
+//
+// In this case, Bar, Quz and NestedBaz will be added into the nested types.
+// Since free field numbers of group types will not be printed, this makes sure
+// the nested message types in groups will not be dropped. The nested_messages
+// parameter will contain the direct children (when groups are ignored in the
+// tree) of the given descriptor for the caller to traverse. The declaration
+// order of the nested messages is also preserved.
+typedef std::pair<int, int> FieldRange;
+void GatherOccupiedFieldRanges(
+ const Descriptor* descriptor, std::set<FieldRange>* ranges,
+ std::vector<const Descriptor*>* nested_messages) {
+ std::set<const Descriptor*> groups;
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* fd = descriptor->field(i);
+ ranges->insert(FieldRange(fd->number(), fd->number() + 1));
+ if (fd->type() == FieldDescriptor::TYPE_GROUP) {
+ groups.insert(fd->message_type());
+ }
+ }
+ for (int i = 0; i < descriptor->extension_range_count(); ++i) {
+ ranges->insert(FieldRange(descriptor->extension_range(i)->start,
+ descriptor->extension_range(i)->end));
+ }
+ for (int i = 0; i < descriptor->reserved_range_count(); ++i) {
+ ranges->insert(FieldRange(descriptor->reserved_range(i)->start,
+ descriptor->reserved_range(i)->end));
+ }
+ // Handle the nested messages/groups in declaration order to make it
+ // post-order strict.
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ const Descriptor* nested_desc = descriptor->nested_type(i);
+ if (groups.find(nested_desc) != groups.end()) {
+ GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages);
+ } else {
+ nested_messages->push_back(nested_desc);
+ }
+ }
+}
+
+// Utility function for PrintFreeFieldNumbers.
+// Actually prints the formatted free field numbers for given message name and
+// occupied ranges.
+void FormatFreeFieldNumbers(const std::string& name,
+ const std::set<FieldRange>& ranges) {
+ std::string output;
+ StringAppendF(&output, "%-35s free:", name.c_str());
+ int next_free_number = 1;
+ for (std::set<FieldRange>::const_iterator i = ranges.begin();
+ i != ranges.end(); ++i) {
+ // This happens when groups re-use parent field numbers, in which
+ // case we skip the FieldRange entirely.
+ if (next_free_number >= i->second) continue;
+
+ if (next_free_number < i->first) {
+ if (next_free_number + 1 == i->first) {
+ // Singleton
+ StringAppendF(&output, " %d", next_free_number);
+ } else {
+ // Range
+ StringAppendF(&output, " %d-%d", next_free_number, i->first - 1);
+ }
+ }
+ next_free_number = i->second;
+ }
+ if (next_free_number <= FieldDescriptor::kMaxNumber) {
+ StringAppendF(&output, " %d-INF", next_free_number);
+ }
+ std::cout << output << std::endl;
+}
+
+} // namespace
+
+void CommandLineInterface::PrintFreeFieldNumbers(const Descriptor* descriptor) {
+ std::set<FieldRange> ranges;
+ std::vector<const Descriptor*> nested_messages;
+ GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
+
+ for (int i = 0; i < nested_messages.size(); ++i) {
+ PrintFreeFieldNumbers(nested_messages[i]);
+ }
+ FormatFreeFieldNumbers(descriptor->full_name(), ranges);
+}
+
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.h b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.h
new file mode 100644
index 00000000..4d37bd6d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface.h
@@ -0,0 +1,462 @@
+// 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.
+//
+// Implements the Protocol Compiler front-end such that it may be reused by
+// custom compilers written to support other languages.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
+#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <stubs/common.h>
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor; // descriptor.h
+class DescriptorDatabase; // descriptor_database.h
+class DescriptorPool; // descriptor.h
+class FileDescriptor; // descriptor.h
+class FileDescriptorSet; // descriptor.h
+class FileDescriptorProto; // descriptor.pb.h
+template <typename T>
+class RepeatedPtrField; // repeated_field.h
+class SimpleDescriptorDatabase; // descriptor_database.h
+
+namespace compiler {
+
+class CodeGenerator; // code_generator.h
+class GeneratorContext; // code_generator.h
+class DiskSourceTree; // importer.h
+
+// This class implements the command-line interface to the protocol compiler.
+// It is designed to make it very easy to create a custom protocol compiler
+// supporting the languages of your choice. For example, if you wanted to
+// create a custom protocol compiler binary which includes both the regular
+// C++ support plus support for your own custom output "Foo", you would
+// write a class "FooGenerator" which implements the CodeGenerator interface,
+// then write a main() procedure like this:
+//
+// int main(int argc, char* argv[]) {
+// google::protobuf::compiler::CommandLineInterface cli;
+//
+// // Support generation of C++ source and headers.
+// google::protobuf::compiler::cpp::CppGenerator cpp_generator;
+// cli.RegisterGenerator("--cpp_out", &cpp_generator,
+// "Generate C++ source and header.");
+//
+// // Support generation of Foo code.
+// FooGenerator foo_generator;
+// cli.RegisterGenerator("--foo_out", &foo_generator,
+// "Generate Foo file.");
+//
+// return cli.Run(argc, argv);
+// }
+//
+// The compiler is invoked with syntax like:
+// protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
+//
+// The .proto file to compile can be specified on the command line using either
+// its physical file path, or a virtual path relative to a directory specified
+// in --proto_path. For example, for src/foo.proto, the following two protoc
+// invocations work the same way:
+// 1. protoc --proto_path=src src/foo.proto (physical file path)
+// 2. protoc --proto_path=src foo.proto (virtual path relative to src)
+//
+// If a file path can be interpreted both as a physical file path and as a
+// relative virtual path, the physical file path takes precedence.
+//
+// For a full description of the command-line syntax, invoke it with --help.
+class PROTOC_EXPORT CommandLineInterface {
+ public:
+ static const char* const kPathSeparator;
+
+ CommandLineInterface();
+ ~CommandLineInterface();
+
+ // Register a code generator for a language.
+ //
+ // Parameters:
+ // * flag_name: The command-line flag used to specify an output file of
+ // this type. The name must start with a '-'. If the name is longer
+ // than one letter, it must start with two '-'s.
+ // * generator: The CodeGenerator which will be called to generate files
+ // of this type.
+ // * help_text: Text describing this flag in the --help output.
+ //
+ // Some generators accept extra parameters. You can specify this parameter
+ // on the command-line by placing it before the output directory, separated
+ // by a colon:
+ // protoc --foo_out=enable_bar:outdir
+ // The text before the colon is passed to CodeGenerator::Generate() as the
+ // "parameter".
+ void RegisterGenerator(const std::string& flag_name, CodeGenerator* generator,
+ const std::string& help_text);
+
+ // Register a code generator for a language.
+ // Besides flag_name you can specify another option_flag_name that could be
+ // used to pass extra parameters to the registered code generator.
+ // Suppose you have registered a generator by calling:
+ // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
+ // Then you could invoke the compiler with a command like:
+ // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
+ // This will pass "enable_bar,enable_baz" as the parameter to the generator.
+ void RegisterGenerator(const std::string& flag_name,
+ const std::string& option_flag_name,
+ CodeGenerator* generator,
+ const std::string& help_text);
+
+ // Enables "plugins". In this mode, if a command-line flag ends with "_out"
+ // but does not match any registered generator, the compiler will attempt to
+ // find a "plugin" to implement the generator. Plugins are just executables.
+ // They should live somewhere in the PATH.
+ //
+ // The compiler determines the executable name to search for by concatenating
+ // exe_name_prefix with the unrecognized flag name, removing "_out". So, for
+ // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
+ // the compiler will try to run the program "protoc-gen-foo".
+ //
+ // The plugin program should implement the following usage:
+ // 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 (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
+ // stdout. The names should be relative to the output directory, NOT absolute
+ // 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 std::string& exe_name_prefix);
+
+ // Run the Protocol Compiler with the given command-line parameters.
+ // Returns the error code which should be returned by main().
+ //
+ // It may not be safe to call Run() in a multi-threaded environment because
+ // it calls strerror(). I'm not sure why you'd want to do this anyway.
+ int Run(int argc, const char* const argv[]);
+
+ // DEPRECATED. Calling this method has no effect. Protocol compiler now
+ // always try to find the .proto file relative to the current directory
+ // first and if the file is not found, it will then treat the input path
+ // as a virtual path.
+ void SetInputsAreProtoPathRelative(bool /* enable */) {}
+
+ // Provides some text which will be printed when the --version flag is
+ // used. The version of libprotoc will also be printed on the next line
+ // after this text.
+ void SetVersionInfo(const std::string& text) { version_info_ = text; }
+
+
+ private:
+ // -----------------------------------------------------------------
+
+ class ErrorPrinter;
+ class GeneratorContextImpl;
+ class MemoryOutputStream;
+ typedef std::unordered_map<std::string, std::unique_ptr<GeneratorContextImpl>>
+ GeneratorContextMap;
+
+ // Clear state from previous Run().
+ void Clear();
+
+ // Remaps the proto file so that it is relative to one of the directories
+ // in proto_path_. Returns false if an error occurred.
+ bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree,
+ std::string* proto,
+ DescriptorDatabase* fallback_database);
+
+ // Remaps each file in input_files_ so that it is relative to one of the
+ // directories in proto_path_. Returns false if an error occurred.
+ bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
+ DescriptorDatabase* fallback_database);
+
+ // Fails if these files use proto3 optional and the code generator doesn't
+ // support it. This is a permanent check.
+ bool EnforceProto3OptionalSupport(
+ const std::string& codegen_name, uint64_t supported_features,
+ const std::vector<const FileDescriptor*>& parsed_files) const;
+
+
+ // Return status for ParseArguments() and InterpretArgument().
+ enum ParseArgumentStatus {
+ PARSE_ARGUMENT_DONE_AND_CONTINUE,
+ PARSE_ARGUMENT_DONE_AND_EXIT,
+ PARSE_ARGUMENT_FAIL
+ };
+
+ // Parse all command-line arguments.
+ ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
+
+ // Read an argument file and append the file's content to the list of
+ // arguments. Return false if the file cannot be read.
+ bool ExpandArgumentFile(const std::string& file,
+ std::vector<std::string>* arguments);
+
+ // 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.
+ //
+ // Examples:
+ // "-Isrc/protos" ->
+ // name = "-I", value = "src/protos"
+ // "--cpp_out=src/foo.pb2.cc" ->
+ // name = "--cpp_out", value = "src/foo.pb2.cc"
+ // "foo.proto" ->
+ // name = "", value = "foo.proto"
+ bool ParseArgument(const char* arg, std::string* name, std::string* value);
+
+ // Interprets arguments parsed with ParseArgument.
+ ParseArgumentStatus InterpretArgument(const std::string& name,
+ const std::string& value);
+
+ // Print the --help text to stderr.
+ void PrintHelpText();
+
+ // Loads proto_path_ into the provided source_tree.
+ bool InitializeDiskSourceTree(DiskSourceTree* source_tree,
+ DescriptorDatabase* fallback_database);
+
+ // Verify that all the input files exist in the given database.
+ bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database);
+
+ // Parses input_files_ into parsed_files
+ bool ParseInputFiles(DescriptorPool* descriptor_pool,
+ DiskSourceTree* source_tree,
+ std::vector<const FileDescriptor*>* parsed_files);
+
+ // Generate the given output file from the given input.
+ struct OutputDirective; // see below
+ bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
+ const OutputDirective& output_directive,
+ GeneratorContext* generator_context);
+ bool GeneratePluginOutput(
+ const std::vector<const FileDescriptor*>& parsed_files,
+ const std::string& plugin_name, const std::string& parameter,
+ GeneratorContext* generator_context, std::string* error);
+
+ // Implements --encode and --decode.
+ bool EncodeOrDecode(const DescriptorPool* pool);
+
+ // Implements the --descriptor_set_out option.
+ 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
+ // protos will be ordered such that every file is listed before any file that
+ // depends on it, so that you can call DescriptorPool::BuildFile() on them
+ // 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,
+ 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]).
+ std::string executable_name_;
+
+ // Version info set with SetVersionInfo().
+ std::string version_info_;
+
+ // Registered generators.
+ struct GeneratorInfo {
+ std::string flag_name;
+ std::string option_flag_name;
+ CodeGenerator* generator;
+ std::string help_text;
+ };
+ typedef std::map<std::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.
+ std::map<std::string, std::string> generator_parameters_;
+ // Similar to generator_parameters_, but stores the parameters for plugins.
+ std::map<std::string, std::string> plugin_parameters_;
+
+ // See AllowPlugins(). If this is empty, plugins aren't allowed.
+ std::string plugin_prefix_;
+
+ // 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.
+ std::map<std::string, std::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_PRINT, // Print mode: print info of the given .proto files and exit.
+ };
+
+ Mode mode_ = MODE_COMPILE;
+
+ enum PrintMode {
+ PRINT_NONE, // Not in MODE_PRINT
+ PRINT_FREE_FIELDS, // --print_free_fields
+ };
+
+ PrintMode print_mode_ = PRINT_NONE;
+
+ enum ErrorFormat {
+ ERROR_FORMAT_GCC, // GCC error output format (default).
+ ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
+ };
+
+ ErrorFormat error_format_ = ERROR_FORMAT_GCC;
+
+ // True if we should treat warnings as errors that fail the compilation.
+ bool fatal_warnings_ = false;
+
+ std::vector<std::pair<std::string, std::string> >
+ proto_path_; // Search path for proto files.
+ std::vector<std::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<std::string> direct_dependencies_;
+ bool direct_dependencies_explicitly_set_ = false;
+
+ // 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.
+ std::string direct_dependencies_violation_msg_;
+
+ // output_directives_ lists all the files we are supposed to output and what
+ // generator to use for each.
+ struct OutputDirective {
+ std::string name; // E.g. "--foo_out"
+ CodeGenerator* generator; // NULL for plugins
+ std::string parameter;
+ std::string output_location;
+ };
+ std::vector<OutputDirective> output_directives_;
+
+ // When using --encode or --decode, this names the type we are encoding or
+ // decoding. (Empty string indicates --decode_raw.)
+ std::string codec_type_;
+
+ // If --descriptor_set_in was given, these are filenames containing
+ // parsed FileDescriptorSets to be used for loading protos. Otherwise, empty.
+ std::vector<std::string> descriptor_set_in_names_;
+
+ // If --descriptor_set_out was given, this is the filename to which the
+ // FileDescriptorSet should be written. Otherwise, empty.
+ std::string descriptor_set_out_name_;
+
+ // If --dependency_out was given, this is the path to the file where the
+ // dependency file will be written. Otherwise, empty.
+ std::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.
+ bool imports_in_descriptor_set_;
+
+ // True if --include_source_info was given, meaning that we should not strip
+ // SourceCodeInfo from the DescriptorSet.
+ bool source_info_in_descriptor_set_ = false;
+
+ // Was the --disallow_services flag used?
+ bool disallow_services_ = false;
+
+ // When using --encode, this will be passed to SetSerializationDeterministic.
+ bool deterministic_output_ = false;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface_unittest.cc
new file mode 100644
index 00000000..78c13f61
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/command_line_interface_unittest.cc
@@ -0,0 +1,2760 @@
+// 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 <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cstdint>
+
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <stubs/stringprintf.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <any.pb.h>
+#include <compiler/mock_code_generator.h>
+#include <compiler/subprocess.h>
+#include <compiler/code_generator.h>
+#include <compiler/command_line_interface.h>
+#include <test_util2.h>
+#include <unittest.pb.h>
+#include <unittest_custom_options.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <descriptor.pb.h>
+#include <descriptor.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <io/io_win32.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::io::win32::access;
+using google::protobuf::io::win32::close;
+using google::protobuf::io::win32::dup;
+using google::protobuf::io::win32::dup2;
+using google::protobuf::io::win32::open;
+using google::protobuf::io::win32::write;
+#endif
+
+// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
+// which case tcmalloc will print warnings that fail the plugin tests.
+#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
+
+namespace {
+
+bool FileExists(const std::string& path) {
+ return File::Exists(path);
+}
+
+class CommandLineInterfaceTest : public testing::Test {
+ protected:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ // Runs the CommandLineInterface with the given command line. The
+ // command is automatically split on spaces, and the string "$tmpdir"
+ // is replaced with TestTempDir().
+ void Run(const std::string& command);
+ void RunWithArgs(std::vector<std::string> args);
+
+ // -----------------------------------------------------------------
+ // Methods to set up the test (called before Run()).
+
+ class NullCodeGenerator;
+
+ // Normally plugins are allowed for all tests. Call this to explicitly
+ // disable them.
+ void DisallowPlugins() { disallow_plugins_ = true; }
+
+ // Create a temp file within temp_directory_ with the given name.
+ // The containing directory is also created if necessary.
+ void CreateTempFile(const std::string& name, const std::string& contents);
+
+ // Create a subdirectory within temp_directory_.
+ void CreateTempDir(const std::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
+
+ // -----------------------------------------------------------------
+ // Methods to check the test results (called after Run()).
+
+ // Checks that no text was written to stderr during Run(), and Run()
+ // returned 0.
+ void ExpectNoErrors();
+
+ // Checks that Run() returned non-zero and the stderr output is exactly
+ // the text given. expected_test may contain references to "$tmpdir",
+ // which will be replaced by the temporary directory path.
+ void ExpectErrorText(const std::string& expected_text);
+
+ // Checks that Run() returned non-zero and the stderr contains the given
+ // substring.
+ void ExpectErrorSubstring(const std::string& expected_substring);
+
+ // Checks that Run() returned zero and the stderr contains the given
+ // substring.
+ void ExpectWarningSubstring(const std::string& expected_substring);
+
+ // Checks that the captured stdout is the same as the expected_text.
+ void ExpectCapturedStdout(const std::string& expected_text);
+
+ // Checks that Run() returned zero and the stdout contains the given
+ // substring.
+ void ExpectCapturedStdoutSubstringWithZeroReturnCode(
+ const std::string& expected_substring);
+
+ // Checks that Run() returned zero and the stderr contains the given
+ // substring.
+ void ExpectCapturedStderrSubstringWithZeroReturnCode(
+ const std::string& expected_substring);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
+ // does not fail otherwise.
+ bool HasAlternateErrorSubstring(const std::string& expected_substring);
+#endif // _WIN32 && !__CYGWIN__
+
+ // Checks that MockCodeGenerator::Generate() was called in the given
+ // context (or the generator in test_plugin.cc, which produces the same
+ // output). That is, this tests if the generator with the given name
+ // was called with the given parameter and proto file and produced the
+ // given output file. This is checked by reading the output file and
+ // checking that it contains the content that MockCodeGenerator would
+ // generate given these inputs. message_name is the name of the first
+ // message that appeared in the proto file; this is just to make extra
+ // sure that the correct file was parsed.
+ void ExpectGenerated(const std::string& generator_name,
+ const std::string& parameter,
+ const std::string& proto_name,
+ const std::string& message_name);
+ void ExpectGenerated(const std::string& generator_name,
+ const std::string& parameter,
+ const std::string& proto_name,
+ const std::string& message_name,
+ const std::string& output_directory);
+ void ExpectGeneratedWithMultipleInputs(const std::string& generator_name,
+ const std::string& all_proto_names,
+ const std::string& proto_name,
+ const std::string& message_name);
+ void ExpectGeneratedWithInsertions(const std::string& generator_name,
+ const std::string& parameter,
+ const std::string& insertions,
+ const std::string& proto_name,
+ const std::string& message_name);
+ void CheckGeneratedAnnotations(const std::string& name,
+ const std::string& file);
+
+#if defined(_WIN32)
+ void ExpectNullCodeGeneratorCalled(const std::string& parameter);
+#endif // _WIN32
+
+
+ void ReadDescriptorSet(const std::string& filename,
+ FileDescriptorSet* descriptor_set);
+
+ void WriteDescriptorSet(const std::string& filename,
+ const FileDescriptorSet* descriptor_set);
+
+ void ExpectFileContent(const std::string& filename,
+ const std::string& content);
+
+ // The default code generators support all features. Use this to create a
+ // code generator that omits the given feature(s).
+ void CreateGeneratorWithMissingFeatures(const std::string& name,
+ const std::string& description,
+ uint64_t features) {
+ MockCodeGenerator* generator = new MockCodeGenerator(name);
+ generator->SuppressFeatures(features);
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator(name, generator, description);
+ }
+
+ private:
+ // The object we are testing.
+ CommandLineInterface cli_;
+
+ // Was DisallowPlugins() called?
+ bool disallow_plugins_;
+
+ // We create a directory within TestTempDir() in order to add extra
+ // protection against accidentally deleting user files (since we recursively
+ // delete this directory during the test). This is the full path of that
+ // directory.
+ std::string temp_directory_;
+
+ // The result of Run().
+ int return_code_;
+
+ // The captured stderr output.
+ std::string error_text_;
+
+ // The captured stdout.
+ std::string captured_stdout_;
+
+ // Pointers which need to be deleted later.
+ std::vector<CodeGenerator*> mock_generators_to_delete_;
+
+ NullCodeGenerator* null_generator_;
+};
+
+class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
+ public:
+ NullCodeGenerator() : called_(false) {}
+ ~NullCodeGenerator() {}
+
+ mutable bool called_;
+ mutable std::string parameter_;
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const {
+ called_ = true;
+ parameter_ = parameter;
+ return true;
+ }
+};
+
+// ===================================================================
+
+void CommandLineInterfaceTest::SetUp() {
+ temp_directory_ = TestTempDir() + "/proto2_cli_test_temp";
+
+ // If the temp directory already exists, it must be left over from a
+ // previous run. Delete it.
+ if (FileExists(temp_directory_)) {
+ File::DeleteRecursively(temp_directory_, NULL, NULL);
+ }
+
+ // Create the temp directory.
+ GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777));
+
+ // Register generators.
+ CodeGenerator* generator = new MockCodeGenerator("test_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output.");
+ cli_.RegisterGenerator("-t", generator, "Test output.");
+
+ generator = new MockCodeGenerator("alt_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--alt_out", generator, "Alt output.");
+
+ generator = null_generator_ = new NullCodeGenerator();
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--null_out", generator, "Null output.");
+
+
+ disallow_plugins_ = false;
+}
+
+void CommandLineInterfaceTest::TearDown() {
+ // Delete the temp directory.
+ 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++) {
+ delete mock_generators_to_delete_[i];
+ }
+ mock_generators_to_delete_.clear();
+}
+
+void CommandLineInterfaceTest::Run(const std::string& command) {
+ RunWithArgs(Split(command, " ", true));
+}
+
+void CommandLineInterfaceTest::RunWithArgs(std::vector<std::string> args) {
+ if (!disallow_plugins_) {
+ cli_.AllowPlugins("prefix-");
+ std::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.
+ // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program
+ // wrapped in this way (e.g. protobuf-tests.exe) tries to execute
+ // another
+ // program wrapped in this way (e.g. test_plugin.exe), the latter fails
+ // with error code 127 and no explanation message. Presumably the
+ // problem
+ // is that the wrapper for protobuf-tests.exe set some environment
+ // variables that confuse the wrapper for test_plugin.exe. Luckily, it
+ // turns out that if we simply invoke the wrapped test_plugin.exe
+ // directly, it works -- I guess the environment variables set by the
+ // protobuf-tests.exe wrapper happen to be correct for it too. So we do
+ // that.
+ ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW)
+ "test_plugin.exe", // Other Win32 (MSVC)
+ "test_plugin", // Unix
+ };
+ 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()) {
+ GOOGLE_LOG(ERROR)
+ << "Plugin executable not found. Plugin tests are likely to fail.";
+ } else {
+ args.push_back("--plugin=prefix-gen-plug=" + plugin_path);
+ }
+ }
+
+ std::unique_ptr<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
+}
+
+// -------------------------------------------------------------------
+
+void CommandLineInterfaceTest::CreateTempFile(const std::string& name,
+ const std::string& contents) {
+ // Create parent directory, if necessary.
+ std::string::size_type slash_pos = name.find_last_of('/');
+ if (slash_pos != std::string::npos) {
+ std::string dir = name.substr(0, slash_pos);
+ if (!FileExists(temp_directory_ + "/" + dir)) {
+ GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir,
+ 0777));
+ }
+ }
+
+ // Write file.
+ std::string full_name = temp_directory_ + "/" + name;
+ GOOGLE_CHECK_OK(File::SetContents(
+ full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
+ true));
+}
+
+void CommandLineInterfaceTest::CreateTempDir(const std::string& name) {
+ GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name,
+ 0777));
+}
+
+// -------------------------------------------------------------------
+
+void CommandLineInterfaceTest::ExpectNoErrors() {
+ EXPECT_EQ(0, return_code_);
+ EXPECT_EQ("", error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectErrorText(
+ const std::string& expected_text) {
+ EXPECT_NE(0, return_code_);
+ EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true),
+ error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectErrorSubstring(
+ const std::string& expected_substring) {
+ EXPECT_NE(0, return_code_);
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectWarningSubstring(
+ const std::string& expected_substring) {
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+ EXPECT_EQ(0, return_code_);
+}
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
+ const std::string& expected_substring) {
+ EXPECT_NE(0, return_code_);
+ return error_text_.find(expected_substring) != std::string::npos;
+}
+#endif // _WIN32 && !__CYGWIN__
+
+void CommandLineInterfaceTest::ExpectGenerated(
+ const std::string& generator_name, const std::string& parameter,
+ const std::string& proto_name, const std::string& message_name) {
+ MockCodeGenerator::ExpectGenerated(generator_name, parameter, "", proto_name,
+ message_name, proto_name, temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGenerated(
+ const std::string& generator_name, const std::string& parameter,
+ const std::string& proto_name, const std::string& message_name,
+ const std::string& output_directory) {
+ MockCodeGenerator::ExpectGenerated(generator_name, parameter, "", proto_name,
+ message_name, proto_name,
+ temp_directory_ + "/" + output_directory);
+}
+
+void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
+ const std::string& generator_name, const std::string& all_proto_names,
+ const std::string& proto_name, const std::string& message_name) {
+ MockCodeGenerator::ExpectGenerated(generator_name, "", "", proto_name,
+ message_name, all_proto_names,
+ temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
+ const std::string& generator_name, const std::string& parameter,
+ const std::string& insertions, const std::string& proto_name,
+ const std::string& message_name) {
+ MockCodeGenerator::ExpectGenerated(generator_name, parameter, insertions,
+ proto_name, message_name, proto_name,
+ temp_directory_);
+}
+
+void CommandLineInterfaceTest::CheckGeneratedAnnotations(
+ const std::string& name, const std::string& file) {
+ MockCodeGenerator::CheckGeneratedAnnotations(name, file, temp_directory_);
+}
+
+#if defined(_WIN32)
+void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
+ const std::string& parameter) {
+ EXPECT_TRUE(null_generator_->called_);
+ EXPECT_EQ(parameter, null_generator_->parameter_);
+}
+#endif // _WIN32
+
+
+void CommandLineInterfaceTest::ReadDescriptorSet(
+ const std::string& filename, FileDescriptorSet* descriptor_set) {
+ std::string path = temp_directory_ + "/" + filename;
+ std::string file_contents;
+ GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
+
+ if (!descriptor_set->ParseFromString(file_contents)) {
+ FAIL() << "Could not parse file contents: " << path;
+ }
+}
+
+void CommandLineInterfaceTest::WriteDescriptorSet(
+ const std::string& filename, const FileDescriptorSet* descriptor_set) {
+ std::string binary_proto;
+ GOOGLE_CHECK(descriptor_set->SerializeToString(&binary_proto));
+ CreateTempFile(filename, binary_proto);
+}
+
+void CommandLineInterfaceTest::ExpectCapturedStdout(
+ const std::string& expected_text) {
+ EXPECT_EQ(expected_text, captured_stdout_);
+}
+
+void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode(
+ const std::string& expected_substring) {
+ EXPECT_EQ(0, return_code_);
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring,
+ captured_stdout_);
+}
+
+void CommandLineInterfaceTest::ExpectCapturedStderrSubstringWithZeroReturnCode(
+ const std::string& expected_substring) {
+ EXPECT_EQ(0, return_code_);
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
+void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename,
+ const std::string& content) {
+ std::string path = temp_directory_ + "/" + filename;
+ std::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) {
+ // Test that the common case works.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, BasicOutput_DescriptorSetIn) {
+ // Test that the common case works.
+ FileDescriptorSet file_descriptor_set;
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, BasicPlugin) {
+ // Test that basic plugins work.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, BasicPlugin_DescriptorSetIn) {
+ // Test that basic plugins work.
+
+ FileDescriptorSet file_descriptor_set;
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
+ // Invoke a generator and a plugin at the same time.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin_DescriptorSetIn) {
+ // Invoke a generator and a plugin at the same time.
+
+ FileDescriptorSet file_descriptor_set;
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputs) {
+ // Test parsing multiple input files.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto bar.proto");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputs_DescriptorSetIn) {
+ // Test parsing multiple input files.
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_message_type()->set_name("Bar");
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto bar.proto");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputs_UnusedImport_DescriptorSetIn) {
+ // Test unused import warning is not raised when descriptor_set_in is called
+ // and custom options are in unknown field instead of uninterpreted_options.
+ FileDescriptorSet file_descriptor_set;
+
+ const FileDescriptor* descriptor_file =
+ FileDescriptorProto::descriptor()->file();
+ descriptor_file->CopyTo(file_descriptor_set.add_file());
+
+ FileDescriptorProto& any_proto = *file_descriptor_set.add_file();
+ google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
+
+ const FileDescriptor* custom_file =
+ protobuf_unittest::AggregateMessage::descriptor()->file();
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ custom_file->CopyTo(file_descriptor_proto);
+ file_descriptor_proto->set_name("custom_options.proto");
+ // Add a custom message option.
+ FieldDescriptorProto* extension_option =
+ file_descriptor_proto->add_extension();
+ extension_option->set_name("unknown_option");
+ extension_option->set_extendee(".google.protobuf.MessageOptions");
+ extension_option->set_number(1111);
+ extension_option->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ extension_option->set_type(FieldDescriptorProto::TYPE_INT64);
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("import_custom_unknown_options.proto");
+ file_descriptor_proto->add_dependency("custom_options.proto");
+ // Add custom message option to unknown field. This custom option is
+ // not known in generated pool, thus option will be in unknown fields.
+ file_descriptor_proto->add_message_type()->set_name("Bar");
+ file_descriptor_proto->mutable_message_type(0)
+ ->mutable_options()
+ ->mutable_unknown_fields()
+ ->AddVarint(1111, 2222);
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin "
+ "import_custom_unknown_options.proto");
+
+ // TODO(jieluo): Fix this test. This test case only happens when
+ // CommandLineInterface::Run() is used instead of invoke protoc combined
+ // with descriptor_set_in, and same custom options are defined in both
+ // generated pool and descriptor_set_in. There's no such uages for now but
+ // still need to be fixed.
+ /*
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("import_custom_extension_options.proto");
+ file_descriptor_proto->add_dependency("custom_options.proto");
+ // Add custom message option to unknown field. This custom option is
+ // also defined in generated pool, thus option will be in extensions.
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+ file_descriptor_proto->mutable_message_type(0)
+ ->mutable_options()
+ ->mutable_unknown_fields()
+ ->AddVarint(protobuf_unittest::message_opt1.number(), 2222);
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin import_custom_unknown_options.proto "
+ "import_custom_extension_options.proto");
+ */
+
+ ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
+ // Test parsing multiple input files with an import of a separate file.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"baz.proto\";\n"
+ "message Bar {\n"
+ " optional Baz a = 1;\n"
+ "}\n");
+ CreateTempFile("baz.proto",
+ "syntax = \"proto2\";\n"
+ "message Baz {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto bar.proto");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) {
+ // Test parsing multiple input files with an import of a separate file.
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_dependency("baz.proto");
+ DescriptorProto* message = file_descriptor_proto->add_message_type();
+ message->set_name("Bar");
+ FieldDescriptorProto* field = message->add_field();
+ field->set_type_name("Baz");
+ field->set_name("a");
+ field->set_number(1);
+
+ WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+ file_descriptor_set.clear_file();
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("baz.proto");
+ file_descriptor_proto->add_message_type()->set_name("Baz");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bat.proto");
+ file_descriptor_proto->add_dependency("baz.proto");
+ message = file_descriptor_proto->add_message_type();
+ message->set_name("Bat");
+ field = message->add_field();
+ field->set_type_name("Baz");
+ field->set_name("a");
+ field->set_number(1);
+
+ WriteDescriptorSet("baz_and_bat.bin", &file_descriptor_set);
+ Run(strings::Substitute(
+ "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+ "--descriptor_set_in=$0 foo.proto bar.proto",
+ std::string("$tmpdir/foo_and_bar.bin") +
+ CommandLineInterface::kPathSeparator + "$tmpdir/baz_and_bat.bin"));
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+
+ Run(strings::Substitute(
+ "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+ "--descriptor_set_in=$0 baz.proto bat.proto",
+ std::string("$tmpdir/foo_and_bar.bin") +
+ CommandLineInterface::kPathSeparator + "$tmpdir/baz_and_bat.bin"));
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+ "baz.proto", "Baz");
+ ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+ "bat.proto", "Bat");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+ "baz.proto", "Baz");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+ "bat.proto", "Bat");
+}
+
+TEST_F(CommandLineInterfaceTest,
+ MultipleInputsWithImport_DescriptorSetIn_DuplicateFileDescriptor) {
+ // Test parsing multiple input files with an import of a separate file.
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto foo_file_descriptor_proto;
+ foo_file_descriptor_proto.set_name("foo.proto");
+ foo_file_descriptor_proto.add_message_type()->set_name("Foo");
+
+ file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_dependency("baz.proto");
+ file_descriptor_proto->add_dependency("foo.proto");
+ DescriptorProto* message = file_descriptor_proto->add_message_type();
+ message->set_name("Bar");
+ FieldDescriptorProto* field = message->add_field();
+ field->set_type_name("Baz");
+ field->set_name("a");
+ field->set_number(1);
+ field = message->add_field();
+ field->set_type_name("Foo");
+ field->set_name("f");
+ field->set_number(2);
+ WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+ file_descriptor_set.clear_file();
+ file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("baz.proto");
+ file_descriptor_proto->add_dependency("foo.proto");
+ message = file_descriptor_proto->add_message_type();
+ message->set_name("Baz");
+ field = message->add_field();
+ field->set_type_name("Foo");
+ field->set_name("f");
+ field->set_number(1);
+ WriteDescriptorSet("foo_and_baz.bin", &file_descriptor_set);
+
+ Run(strings::Substitute(
+ "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+ "--descriptor_set_in=$0 bar.proto",
+ std::string("$tmpdir/foo_and_bar.bin") +
+ CommandLineInterface::kPathSeparator + "$tmpdir/foo_and_baz.bin"));
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "bar.proto", "Bar");
+ ExpectGenerated("test_plugin", "", "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest,
+ MultipleInputsWithImport_DescriptorSetIn_MissingImport) {
+ // Test parsing multiple input files with an import of a separate file.
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_dependency("baz.proto");
+ DescriptorProto* message = file_descriptor_proto->add_message_type();
+ message->set_name("Bar");
+ FieldDescriptorProto* field = message->add_field();
+ field->set_type_name("Baz");
+ field->set_name("a");
+ field->set_number(1);
+
+ WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+ file_descriptor_set.clear_file();
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("baz.proto");
+ file_descriptor_proto->add_message_type()->set_name("Baz");
+
+ WriteDescriptorSet("baz.bin", &file_descriptor_set);
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo_and_bar.bin "
+ "foo.proto bar.proto");
+ ExpectErrorSubstring(
+ "bar.proto: Import \"baz.proto\" was not found or had errors.");
+ ExpectErrorSubstring("bar.proto: \"Baz\" is not defined.");
+}
+
+TEST_F(CommandLineInterfaceTest,
+ InputsOnlyFromDescriptorSetIn_UnusedImportIsNotReported) {
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("unused.proto");
+ file_descriptor_proto->add_message_type()->set_name("Unused");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_dependency("unused.proto");
+ file_descriptor_proto->add_message_type()->set_name("Bar");
+
+ WriteDescriptorSet("unused_and_bar.bin", &file_descriptor_set);
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/unused_and_bar.bin unused.proto bar.proto");
+ ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest,
+ InputsFromDescriptorSetInAndFileSystem_UnusedImportIsReported) {
+ FileDescriptorSet file_descriptor_set;
+
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("unused.proto");
+ file_descriptor_proto->add_message_type()->set_name("Unused");
+
+ file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("bar.proto");
+ file_descriptor_proto->add_dependency("unused.proto");
+ file_descriptor_proto->add_message_type()->set_name("Bar");
+
+ WriteDescriptorSet("unused_and_bar.bin", &file_descriptor_set);
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar bar = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/unused_and_bar.bin "
+ "--proto_path=$tmpdir unused.proto bar.proto foo.proto");
+ // Reporting unused imports here is unfair, since it's unactionable. Notice
+ // the lack of a line number.
+ // TODO(b/144853061): If the file with unused import is from the descriptor
+ // set and not from the file system, suppress the warning.
+ ExpectWarningSubstring("bar.proto: warning: Import unused.proto is unused.");
+}
+
+TEST_F(CommandLineInterfaceTest,
+ OnlyReportsUnusedImportsForFilesBeingGenerated) {
+ CreateTempFile("unused.proto",
+ "syntax = \"proto2\";\n"
+ "message Unused {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"unused.proto\";\n"
+ "message Bar {}\n");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar bar = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+ ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafFirst) {
+ CreateTempFile("unused.proto",
+ "syntax = \"proto2\";\n"
+ "message Unused {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"unused.proto\";\n"
+ "message Bar {}\n");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar bar = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir bar.proto foo.proto");
+ ExpectWarningSubstring(
+ "bar.proto:2:1: warning: Import unused.proto is unused.");
+}
+
+TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafLast) {
+ CreateTempFile("unused.proto",
+ "syntax = \"proto2\";\n"
+ "message Unused {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"unused.proto\";\n"
+ "message Bar {}\n");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar bar = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto bar.proto");
+ ExpectWarningSubstring(
+ "bar.proto:2:1: warning: Import unused.proto is unused.");
+}
+TEST_F(CommandLineInterfaceTest, CreateDirectory) {
+ // Test that when we output to a sub-directory, it is created.
+
+ CreateTempFile("bar/baz/foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempDir("out");
+ CreateTempDir("plugout");
+
+ Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
+ "--proto_path=$tmpdir bar/baz/foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out");
+ ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
+ // Test that generator parameters are correctly parsed from the command line.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
+ // 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 "
+ "--test_opt=foo1 "
+ "--test_out=bar:$tmpdir/a "
+ "--test_opt=foo2 "
+ "--test_out=baz:$tmpdir/b "
+ "--test_opt=foo3 "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo",
+ "a");
+ ExpectGenerated("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_a_opt=Foo "
+ "--unknown_plug_b_opt=Bar "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Unknown flag: --unknown_plug_a_opt");
+ ExpectErrorSubstring("Unknown flag: --unknown_plug_b_opt");
+}
+
+TEST_F(CommandLineInterfaceTest, ExtraPluginParametersForOutParameters) {
+ // This doesn't rely on the plugin having been registered and instead that
+ // the existence of --[name]_out is enough to make the --[name]_opt valid.
+ // However, running out of process plugins found via the search path (i.e. -
+ // not pre registered with --plugin) isn't support in this test suite, so we
+ // list the options pre/post the _out directive, and then include _opt that
+ // will be unknown, and confirm the failure output is about the expected
+ // unknown directive, which means the other were accepted.
+ // NOTE: UnrecognizedExtraParameters confirms that if two unknown _opt
+ // directives appear, they both are reported.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--xyz_opt=foo=bar --xyz_out=$tmpdir "
+ "--abc_out=$tmpdir --abc_opt=foo=bar "
+ "--unknown_plug_opt=Foo "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText("Unknown flag: --unknown_plug_opt\n");
+}
+
+TEST_F(CommandLineInterfaceTest, Insert) {
+ // Test running a generator that inserts code into another's output.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler "
+ "--test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--test_out=insert=test_generator,test_plugin:$tmpdir "
+ "--plug_out=insert=test_generator,test_plugin:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithInsertions("test_generator", "TestParameter",
+ "test_generator,test_plugin", "foo.proto",
+ "Foo");
+ ExpectGeneratedWithInsertions("test_plugin", "TestPluginParameter",
+ "test_generator,test_plugin", "foo.proto",
+ "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) {
+ // Check that annotation spans are updated after insertions.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Annotate {}\n");
+
+ Run("protocol_compiler "
+ "--test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--test_out=insert_endlines=test_generator,test_plugin:$tmpdir "
+ "--plug_out=insert_endlines=test_generator,test_plugin:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ CheckGeneratedAnnotations("test_generator", "foo.proto");
+ CheckGeneratedAnnotations("test_plugin", "foo.proto");
+}
+
+#if defined(_WIN32)
+
+TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
+ // Test that the output path can be a Windows-style path.
+
+ CreateTempFile("foo.proto", "syntax = \"proto2\";\n");
+
+ Run("protocol_compiler --null_out=C:\\ "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectNullCodeGeneratorCalled("");
+}
+
+TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
+ // Test that we can have a windows-style output path and a parameter.
+
+ CreateTempFile("foo.proto", "syntax = \"proto2\";\n");
+
+ Run("protocol_compiler --null_out=bar:C:\\ "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectNullCodeGeneratorCalled("bar");
+}
+
+TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
+ // Test that the directories can end in backslashes. Some users claim this
+ // doesn't work on their system.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir\\ "
+ "--proto_path=$tmpdir\\ foo.proto");
+
+ ExpectNoErrors();
+ 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) {
+ // Test that specifying multiple directories in the proto search path works.
+
+ CreateTempFile("b/bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+ CreateTempFile("a/foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar a = 1;\n"
+ "}\n");
+ CreateTempFile("b/foo.proto", "this should not be parsed\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
+ // Same as PathLookup, but we provide the proto_path in a single flag.
+
+ CreateTempFile("b/bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+ CreateTempFile("a/foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar a = 1;\n"
+ "}\n");
+ CreateTempFile("b/foo.proto", "this should not be parsed\n");
+
+ Run(strings::Substitute(
+ "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto",
+ std::string("$tmpdir/a") + CommandLineInterface::kPathSeparator +
+ "$tmpdir/b"));
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, NonRootMapping) {
+ // Test setting up a search path mapping a directory to a non-root location.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=bar=$tmpdir bar/foo.proto");
+
+ ExpectNoErrors();
+ 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.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ // Create the "a" and "b" sub-directories.
+ CreateTempDir("a");
+ CreateTempDir("b");
+
+ Run("protocol_compiler "
+ "--test_out=$tmpdir/a "
+ "--alt_out=$tmpdir/b "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a");
+ ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
+ // Test that --disallow_services doesn't cause a problem when there are no
+ // services.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --disallow_services --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
+ // Test that --disallow_services produces an error when there are services.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n"
+ "service Bar {}\n");
+
+ Run("protocol_compiler --disallow_services --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("foo.proto: This file contains services");
+}
+
+TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
+ // Test that services work fine as long as --disallow_services is not used.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n"
+ "service Bar {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ 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; }");
+
+ std::vector<std::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.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir $tmpdir/foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
+ 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 --descriptor_set_out=$tmpdir/descriptor_set "
+ "--proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ 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());
+ // foo should come first since the output is in dependency order.
+ // since bar and baz are unordered, they should be in command line order.
+ EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("bar.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(1).message_type(0).name());
+ EXPECT_EQ("foo", descriptor_set.file(1).message_type(0).field(0).name());
+ EXPECT_TRUE(descriptor_set.file(1).message_type(0).field(0).has_json_name());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
+ 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 --descriptor_set_out=$tmpdir/descriptor_set "
+ "--include_source_info --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ 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());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
+ 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 --descriptor_set_out=$tmpdir/descriptor_set "
+ "--include_imports --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ 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]);
+ }
+ EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+ // Descriptor set should not have source code info.
+ EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+ EXPECT_FALSE(descriptor_set.file(1).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
+ 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 --descriptor_set_out=$tmpdir/descriptor_set "
+ "--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ 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]);
+ }
+ EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+ // Source code info included.
+ EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+ 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");
+
+ std::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, TestArgumentFile) {
+ // Test parsing multiple input files using an argument file.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+ CreateTempFile("arguments.txt",
+ "--test_out=$tmpdir\n"
+ "--plug_out=$tmpdir\n"
+ "--proto_path=$tmpdir\n"
+ "--direct_dependencies_violation_msg=%s is not imported\n"
+ "foo.proto\n"
+ "bar.proto");
+
+ Run("protocol_compiler @$tmpdir/arguments.txt");
+
+ ExpectNoErrors();
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+ "bar.proto", "Bar");
+}
+
+
+// -------------------------------------------------------------------
+
+TEST_F(CommandLineInterfaceTest, ParseErrors) {
+ // Test that parse errors are reported.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText(
+ "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) {
+ // Test that parse errors are reported.
+ CreateTempFile("foo.bin", "not a FileDescriptorSet");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+ ExpectErrorText("$tmpdir/foo.bin: Unable to parse.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
+ // Test that parse errors are reported from multiple files.
+
+ // We set up files such that foo.proto actually depends on bar.proto in
+ // two ways: Directly and through baz.proto. bar.proto's errors should
+ // only be reported once.
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+ CreateTempFile("baz.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "import \"baz.proto\";\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText(
+ "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n"
+ "baz.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"
+ "foo.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"
+ "foo.proto:3:1: 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:2:1: File recursively imports itself: "
+ "foo.proto -> foo.proto\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
+ // Test what happens if the input file is not found.
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText(
+ "Could not make proto path relative: foo.proto: No such file or "
+ "directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) {
+ // Test what happens if the input file is not found.
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+ ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
+ // Test what happens when a working-directory-relative input file is not
+ // found.
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir $tmpdir/foo.proto");
+
+ ExpectErrorText(
+ "Could not make proto path relative: $tmpdir/foo.proto: No such file or "
+ "directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
+ // Test what happens when a working-directory-relative input file is not
+ // mapped to a virtual path.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ // Create a directory called "bar" so that we can point --proto_path at it.
+ CreateTempFile("bar/dummy", "");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
+
+ ExpectErrorText(
+ "$tmpdir/foo.proto: File does not reside within any path "
+ "specified using --proto_path (or -I). You must specify a "
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think).\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
+ // Check what happens if the input file is not found *and* is not mapped
+ // in the proto_path.
+
+ // Create a directory called "bar" so that we can point --proto_path at it.
+ CreateTempFile("bar/dummy", "");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
+
+ ExpectErrorText(
+ "Could not make proto path relative: $tmpdir/foo.proto: No such file or "
+ "directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
+ // Test what happens when a working-directory-relative input file is shadowed
+ // by another file in the virtual path.
+
+ CreateTempFile("foo/foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar/foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar "
+ "$tmpdir/bar/foo.proto");
+
+ ExpectErrorText(
+ "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path "
+ "by \"$tmpdir/foo/foo.proto\". Either use the latter "
+ "file as your input or reorder the --proto_path so that the "
+ "former file's location comes first.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
+ // Test what happens if the input file is not found.
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir/foo foo.proto");
+
+ ExpectErrorText(
+ "$tmpdir/foo: warning: directory does not exist.\n"
+ "Could not make proto path relative: foo.proto: No such file or "
+ "directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) {
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto");
+ ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto");
+ ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn_CompileFiles) {
+ // Test what happens if a proto is in a --descriptor_set_in and also exists
+ // on disk.
+ FileDescriptorSet file_descriptor_set;
+
+ // NOTE: This file desc SHOULD be different from the one created as a temp
+ // to make it easier to test that the file was output instead of the
+ // contents of the --descriptor_set_in file.
+ FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+ file_descriptor_proto->set_name("foo.proto");
+ file_descriptor_proto->add_message_type()->set_name("Foo");
+
+ WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message FooBar { required string foo_message = 1; }\n");
+
+ Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+ "--descriptor_set_in=$tmpdir/foo.bin "
+ "--include_source_info "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+
+ EXPECT_EQ(1, descriptor_set.file_size());
+ EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+ // Descriptor set SHOULD have source code info.
+ EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+
+ EXPECT_EQ("FooBar", descriptor_set.file(0).message_type(0).name());
+ EXPECT_EQ("foo_message",
+ descriptor_set.file(0).message_type(0).field(0).name());
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) {
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--dependency_out=$tmpdir/manifest "
+ "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+ ExpectErrorText(
+ "--descriptor_set_in cannot be used with --dependency_out.\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--descriptor_set_in=$tmpdir/foo.bin "
+ "--dependency_out=$tmpdir/manifest foo.proto");
+ ExpectErrorText(
+ "--dependency_out cannot be used with --descriptor_set_in.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingInputError) {
+ // Test that we get an error if no inputs are given.
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir");
+
+ ExpectErrorText("Missing input file.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingOutputError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText("Missing output directives.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputWriteError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ std::string output_file =
+ MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto");
+
+ // Create a directory blocking our output location.
+ CreateTempDir(output_file);
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ // MockCodeGenerator no longer detects an error because we actually write to
+ // an in-memory location first, then dump to disk at the end. This is no
+ // big deal.
+ // ExpectErrorSubstring("MockCodeGenerator detected write error.");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+ return;
+ }
+#endif
+
+ ExpectErrorSubstring(output_file + ": Is a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ std::string output_file =
+ MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto");
+
+ // Create a directory blocking our output location.
+ CreateTempDir(output_file);
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+ return;
+ }
+#endif
+
+ ExpectErrorSubstring(output_file + ": Is a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir/nosuchdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --plug_out=$tmpdir/nosuchdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir/foo.proto "
+ "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Windows with MSVCRT.dll produces EINVAL instead of ENOTDIR.
+ if (HasAlternateErrorSubstring("foo.proto/: Invalid argument")) {
+ return;
+ }
+#endif
+
+ ExpectErrorSubstring("foo.proto/: Not a directory");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Error {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
+ // Test a generator plugin that returns an error.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Error {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
+ // Test a generator plugin that exits with an error code.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Exit {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit.");
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
+ // Test a generator plugin that crashes.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Abort {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort.");
+
+#ifdef _WIN32
+ // Windows doesn't have signals. It looks like abort()ing causes the process
+ // to exit with status code 3, but let's not depend on the exact number here.
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin failed with status code");
+#else
+ // Don't depend on the exact signal number.
+ ExpectErrorSubstring("--plug_out: prefix-gen-plug: Plugin killed by signal");
+#endif
+}
+
+TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_HasSourceCodeInfo {}\n");
+
+ Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "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.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --badplug_out=TestParameter:$tmpdir "
+ "--plugin=prefix-gen-badplug=no_such_file "
+ "--proto_path=$tmpdir error.proto");
+
+#ifdef _WIN32
+ ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " +
+ Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
+#else
+ // Error written to stdout by child process after exec() fails.
+ ExpectErrorSubstring("no_such_file: program not found or is not executable");
+
+ ExpectErrorSubstring(
+ "Please specify a program using absolute path or make sure "
+ "the program is available in your PATH system variable");
+
+ // Error written by parent process when child fails.
+ ExpectErrorSubstring(
+ "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
+#endif
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
+ // Test what happens if plugins aren't allowed.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ DisallowPlugins();
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir error.proto");
+
+ ExpectErrorSubstring("Unknown flag: --plug_out");
+}
+
+TEST_F(CommandLineInterfaceTest, HelpText) {
+ Run("test_exec_name --help");
+
+ ExpectCapturedStdoutSubstringWithZeroReturnCode("Usage: test_exec_name ");
+ ExpectCapturedStdoutSubstringWithZeroReturnCode("--test_out=OUT_DIR");
+ ExpectCapturedStdoutSubstringWithZeroReturnCode("Test output.");
+ ExpectCapturedStdoutSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
+ ExpectCapturedStdoutSubstringWithZeroReturnCode("Alt output.");
+}
+
+TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
+ // Test --error_format=gcc (which is the default, but we want to verify
+ // that it can be set explicitly).
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=gcc foo.proto");
+
+ ExpectErrorText(
+ "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
+ // Test --error_format=msvs
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=msvs foo.proto");
+
+ ExpectErrorText(
+ "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement "
+ "(e.g. \"message\").\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
+ // Test invalid --error_format
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "badsyntax\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir --error_format=invalid foo.proto");
+
+ ExpectErrorText("Unknown error format: invalid\n");
+}
+
+TEST_F(CommandLineInterfaceTest, Warnings) {
+ // Test --fatal_warnings.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n");
+ CreateTempFile("bar.proto", "syntax = \"proto2\";\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+ ExpectCapturedStderrSubstringWithZeroReturnCode(
+ "foo.proto:2:1: warning: Import bar.proto is unused.");
+
+ Run("protocol_compiler --test_out=$tmpdir --fatal_warnings "
+ "--proto_path=$tmpdir foo.proto");
+ ExpectErrorSubstring("foo.proto:2:1: warning: Import bar.proto is unused.");
+}
+
+// -------------------------------------------------------------------
+// Flag parsing tests
+
+TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
+ // Test that a single-character flag works.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler -t$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
+ // Test that separating the flag value with a space works.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --test_out $tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
+ // Test that separating the flag value with a space works for
+ // single-character flags.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler -t $tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingValueError) {
+ // Test that we get an error if a flag is missing its value.
+
+ Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
+
+ ExpectErrorText("Missing value for flag: --test_out\n");
+}
+
+TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
+ // Test that we get an error if the last argument is a flag requiring a
+ // value.
+
+ Run("protocol_compiler --test_out");
+
+ ExpectErrorText("Missing value for flag: --test_out\n");
+}
+
+TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) {
+ CreateTempFile("google/foo.proto",
+ "syntax = \"proto3\";\n"
+ "message Foo {\n"
+ " optional int32 i = 1;\n"
+ "}\n");
+
+ CreateGeneratorWithMissingFeatures("--no_proto3_optional_out",
+ "Doesn't support proto3 optional",
+ CodeGenerator::FEATURE_PROTO3_OPTIONAL);
+
+ Run("protocol_compiler --experimental_allow_proto3_optional "
+ "--proto_path=$tmpdir google/foo.proto --no_proto3_optional_out=$tmpdir");
+
+ ExpectErrorSubstring(
+ "code generator --no_proto3_optional_out hasn't been updated to support "
+ "optional fields in proto3");
+}
+
+TEST_F(CommandLineInterfaceTest, Proto3OptionalAllowWithFlag) {
+ CreateTempFile("google/foo.proto",
+ "syntax = \"proto3\";\n"
+ "message Foo {\n"
+ " optional int32 i = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --experimental_allow_proto3_optional "
+ "--proto_path=$tmpdir google/foo.proto --test_out=$tmpdir");
+ ExpectNoErrors();
+}
+
+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
+// test as a shell script, but we'd like to be able to run the test on
+// platforms that don't have a Bourne-compatible shell available (especially
+// Windows/MSVC).
+
+enum EncodeDecodeTestMode { PROTO_PATH, DESCRIPTOR_SET_IN };
+
+class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
+ protected:
+ virtual void SetUp() {
+ WriteUnittestProtoDescriptorSet();
+ duped_stdin_ = dup(STDIN_FILENO);
+ }
+
+ virtual void TearDown() {
+ dup2(duped_stdin_, STDIN_FILENO);
+ close(duped_stdin_);
+ }
+
+ void RedirectStdinFromText(const std::string& input) {
+ std::string filename = TestTempDir() + "/test_stdin";
+ GOOGLE_CHECK_OK(File::SetContents(filename, input, true));
+ GOOGLE_CHECK(RedirectStdinFromFile(filename));
+ }
+
+ bool RedirectStdinFromFile(const std::string& filename) {
+ int fd = open(filename.c_str(), O_RDONLY);
+ if (fd < 0) return false;
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+ return true;
+ }
+
+ // Remove '\r' characters from text.
+ std::string StripCR(const std::string& text) {
+ std::string result;
+
+ for (int i = 0; i < text.size(); i++) {
+ if (text[i] != '\r') {
+ result.push_back(text[i]);
+ }
+ }
+
+ return result;
+ }
+
+ enum Type { TEXT, BINARY };
+ enum ReturnCode { SUCCESS, ERROR };
+
+ bool Run(const std::string& command, bool specify_proto_files = true) {
+ std::vector<std::string> args;
+ args.push_back("protoc");
+ for (StringPiece split_piece :
+ Split(command, " ", true)) {
+ args.push_back(std::string(split_piece));
+ }
+ if (specify_proto_files) {
+ switch (GetParam()) {
+ case PROTO_PATH:
+ args.push_back("--proto_path=" + TestUtil::TestSourceDir());
+ break;
+ case DESCRIPTOR_SET_IN:
+ args.push_back(StrCat("--descriptor_set_in=",
+ unittest_proto_descriptor_set_filename_));
+ break;
+ default:
+ ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
+ }
+ }
+
+ std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
+ for (int i = 0; i < args.size(); i++) {
+ argv[i] = args[i].c_str();
+ }
+
+ CommandLineInterface cli;
+
+ CaptureTestStdout();
+ CaptureTestStderr();
+
+ int result = cli.Run(args.size(), argv.get());
+
+ captured_stdout_ = GetCapturedTestStdout();
+ captured_stderr_ = GetCapturedTestStderr();
+
+ return result == 0;
+ }
+
+ void ExpectStdoutMatchesBinaryFile(const std::string& filename) {
+ std::string 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.
+ EXPECT_TRUE(captured_stdout_ == expected_output);
+ }
+
+ void ExpectStdoutMatchesTextFile(const std::string& filename) {
+ std::string expected_output;
+ GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true));
+
+ ExpectStdoutMatchesText(expected_output);
+ }
+
+ void ExpectStdoutMatchesText(const std::string& expected_text) {
+ EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_));
+ }
+
+ void ExpectStderrMatchesText(const std::string& expected_text) {
+ EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_));
+ }
+
+ void ExpectStderrContainsText(const std::string& expected_text) {
+ EXPECT_NE(StripCR(captured_stderr_).find(StripCR(expected_text)),
+ std::string::npos);
+ }
+
+ private:
+ void WriteUnittestProtoDescriptorSet() {
+ unittest_proto_descriptor_set_filename_ =
+ TestTempDir() + "/unittest_proto_descriptor_set.bin";
+ FileDescriptorSet file_descriptor_set;
+ protobuf_unittest::TestAllTypes test_all_types;
+ test_all_types.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+ protobuf_unittest_import::ImportMessage import_message;
+ import_message.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+ protobuf_unittest_import::PublicImportMessage public_import_message;
+ public_import_message.descriptor()->file()->CopyTo(
+ file_descriptor_set.add_file());
+ GOOGLE_DCHECK(file_descriptor_set.IsInitialized());
+
+ std::string binary_proto;
+ GOOGLE_CHECK(file_descriptor_set.SerializeToString(&binary_proto));
+ GOOGLE_CHECK_OK(File::SetContents(unittest_proto_descriptor_set_filename_,
+ binary_proto, true));
+ }
+
+ int duped_stdin_;
+ std::string captured_stdout_;
+ std::string captured_stderr_;
+ std::string unittest_proto_descriptor_set_filename_;
+};
+
+TEST_P(EncodeDecodeTest, Encode) {
+ RedirectStdinFromFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/"
+ "testdata/text_format_unittest_data_oneof_implemented.txt"));
+ std::string args;
+ if (GetParam() != DESCRIPTOR_SET_IN) {
+ args.append(
+ TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+ }
+ EXPECT_TRUE(Run(args + " --encode=protobuf_unittest.TestAllTypes"));
+ ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+ ExpectStderrMatchesText("");
+}
+
+TEST_P(EncodeDecodeTest, Decode) {
+ RedirectStdinFromFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+ EXPECT_TRUE(
+ Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+ " --decode=protobuf_unittest.TestAllTypes"));
+ ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/"
+ "testdata/text_format_unittest_data_oneof_implemented.txt"));
+ ExpectStderrMatchesText("");
+}
+
+TEST_P(EncodeDecodeTest, Partial) {
+ RedirectStdinFromText("");
+ EXPECT_TRUE(
+ Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+ " --encode=protobuf_unittest.TestRequired"));
+ ExpectStdoutMatchesText("");
+ ExpectStderrMatchesText(
+ "warning: Input message is missing required fields: a, b, c\n");
+}
+
+TEST_P(EncodeDecodeTest, DecodeRaw) {
+ protobuf_unittest::TestAllTypes message;
+ message.set_optional_int32(123);
+ message.set_optional_string("foo");
+ std::string data;
+ message.SerializeToString(&data);
+
+ RedirectStdinFromText(data);
+ EXPECT_TRUE(Run("--decode_raw", /*specify_proto_files=*/false));
+ ExpectStdoutMatchesText(
+ "1: 123\n"
+ "14: \"foo\"\n");
+ ExpectStderrMatchesText("");
+}
+
+TEST_P(EncodeDecodeTest, UnknownType) {
+ EXPECT_FALSE(
+ Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+ " --encode=NoSuchType"));
+ ExpectStdoutMatchesText("");
+ ExpectStderrMatchesText("Type not defined: NoSuchType\n");
+}
+
+TEST_P(EncodeDecodeTest, ProtoParseError) {
+ EXPECT_FALSE(
+ Run("net/proto2/internal/no_such_file.proto "
+ "--encode=NoSuchType"));
+ ExpectStdoutMatchesText("");
+ ExpectStderrContainsText(
+ "net/proto2/internal/no_such_file.proto: No such file or directory\n");
+}
+
+TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) {
+ RedirectStdinFromFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/"
+ "testdata/text_format_unittest_data_oneof_implemented.txt"));
+ std::string args;
+ if (GetParam() != DESCRIPTOR_SET_IN) {
+ args.append(
+ TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+ }
+ EXPECT_TRUE(Run(
+ args + " --encode=protobuf_unittest.TestAllTypes --deterministic_output"));
+ ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+ ExpectStderrMatchesText("");
+}
+
+TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) {
+ RedirectStdinFromFile(TestUtil::GetTestDataPath(
+ "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+ EXPECT_FALSE(
+ Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+ " --decode=protobuf_unittest.TestAllTypes --deterministic_output"));
+ ExpectStderrMatchesText(
+ "Can only use --deterministic_output with --encode.\n");
+}
+
+INSTANTIATE_TEST_SUITE_P(FileDescriptorSetSource, EncodeDecodeTest,
+ testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN));
+} // anonymous namespace
+
+#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
new file mode 100644
index 00000000..e13b29f9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -0,0 +1,195 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This test insures that net/proto2/proto/descriptor.pb.{h,cc} match exactly
+// what would be generated by the protocol compiler. These files are not
+// generated automatically at build time because they are compiled into the
+// protocol compiler itself. So, if they were auto-generated, you'd have a
+// chicken-and-egg problem.
+//
+// If this test fails, run the script
+// "generate_descriptor_proto.sh" and add
+// descriptor.pb.{h,cc} to your changelist.
+
+#include <map>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_generator.h>
+#include <compiler/importer.h>
+#include <test_util2.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.h>
+#include <stubs/strutil.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <stubs/substitute.h>
+#include <stubs/map_util.h>
+#include <stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+ MockErrorCollector() {}
+ ~MockErrorCollector() {}
+
+ std::string text_;
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, int line, int column,
+ const std::string& message) {
+ strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+ message);
+ }
+};
+
+class MockGeneratorContext : public GeneratorContext {
+ public:
+ void ExpectFileMatches(const std::string& virtual_filename,
+ const std::string& physical_filename) {
+ auto it = files_.find(virtual_filename);
+ ASSERT_TRUE(it != files_.end())
+ << "Generator failed to generate file: " << virtual_filename;
+
+ std::string expected_contents = *it->second;
+ std::string actual_contents;
+ GOOGLE_CHECK_OK(
+ File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename,
+ &actual_contents, true))
+ << physical_filename;
+ CleanStringLineEndings(&actual_contents, false);
+
+#ifdef WRITE_FILES // Define to debug mismatched files.
+ GOOGLE_CHECK_OK(File::SetContents("/tmp/expected.cc", expected_contents,
+ true));
+ GOOGLE_CHECK_OK(
+ File::SetContents("/tmp/actual.cc", actual_contents, true));
+#endif
+
+ ASSERT_EQ(expected_contents, actual_contents)
+ << physical_filename
+ << " needs to be regenerated. Please run "
+ "generate_descriptor_proto.sh. "
+ "Then add this file to your CL.";
+ }
+
+ // implements GeneratorContext --------------------------------------
+
+ virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
+ auto& map_slot = files_[filename];
+ map_slot.reset(new std::string);
+ return new io::StringOutputStream(map_slot.get());
+ }
+
+ private:
+ std::map<std::string, std::unique_ptr<std::string>> files_;
+};
+
+const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT";
+const char kPluginParameter[] = "dllexport_decl=PROTOC_EXPORT";
+
+
+const char* test_protos[][2] = {
+ {"google/protobuf/descriptor", kDescriptorParameter},
+ {"google/protobuf/compiler/plugin", kPluginParameter},
+};
+
+TEST(BootstrapTest, GeneratedFilesMatch) {
+ // We need a mapping from the actual file to virtual and actual path
+ // of the data to compare to.
+ std::map<std::string, std::string> vpath_map;
+ std::map<std::string, std::string> rpath_map;
+ rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
+ "net/proto2/z_generated_example/test_messages_proto2";
+ rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
+ "net/proto2/z_generated_example/test_messages_proto3";
+ rpath_map["net/proto2/internal/proto2_weak"] =
+ "net/proto2/z_generated_example/proto2_weak";
+
+ DiskSourceTree source_tree;
+ source_tree.MapPath("", TestUtil::TestSourceDir());
+
+ for (auto file_parameter : test_protos) {
+ MockErrorCollector error_collector;
+ Importer importer(&source_tree, &error_collector);
+ const FileDescriptor* file =
+ importer.Import(file_parameter[0] + std::string(".proto"));
+ ASSERT_TRUE(file != nullptr)
+ << "Can't import file " << file_parameter[0] + std::string(".proto")
+ << "\n";
+ EXPECT_EQ("", error_collector.text_);
+ CppGenerator generator;
+ MockGeneratorContext context;
+#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
+ generator.set_opensource_runtime(true);
+ generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
+#endif
+ std::string error;
+ ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
+
+ std::string vpath =
+ FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
+ std::string rpath =
+ FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
+ context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
+ context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
+ }
+}
+
+// test Generate in cpp_generator.cc
+TEST(BootstrapTest, OptionNotExist) {
+ cpp::CppGenerator generator;
+ DescriptorPool pool;
+ GeneratorContext* generator_context = nullptr;
+ std::string parameter = "aaa";
+ std::string error;
+ ASSERT_FALSE(generator.Generate(
+ pool.FindFileByName("google/protobuf/descriptor.proto"), parameter,
+ generator_context, &error));
+ EXPECT_EQ(error, "Unknown generator option: " + parameter);
+}
+
+} // namespace
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.cc
new file mode 100644
index 00000000..e2bf2e6f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.cc
@@ -0,0 +1,438 @@
+// 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 <compiler/cpp/cpp_enum.h>
+
+#include <cstdint>
+#include <limits>
+#include <map>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_names.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
+// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
+// generation of the GOOGLE_ARRAYSIZE constant.
+bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
+ int32_t 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 != std::numeric_limits<int32_t>::max();
+}
+
+// Returns the number of unique numeric enum values. This is less than
+// descriptor->value_count() when there are aliased values.
+int CountUniqueValues(const EnumDescriptor* descriptor) {
+ std::set<int> values;
+ for (int i = 0; i < descriptor->value_count(); ++i) {
+ values.insert(descriptor->value(i)->number());
+ }
+ return values.size();
+}
+
+} // namespace
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
+ const std::map<std::string, std::string>& vars,
+ const Options& options)
+ : descriptor_(descriptor),
+ classname_(ClassName(descriptor, false)),
+ options_(options),
+ generate_array_size_(ShouldGenerateArraySize(descriptor)),
+ variables_(vars) {
+ variables_["classname"] = classname_;
+ variables_["classtype"] = QualifiedClassName(descriptor_, options);
+ variables_["short_name"] = descriptor_->name();
+ variables_["nested_name"] = descriptor_->name();
+ variables_["resolved_name"] = ResolveKeyword(descriptor_->name());
+ variables_["prefix"] =
+ (descriptor_->containing_type() == NULL) ? "" : classname_ + "_";
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::GenerateDefinition(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format("enum ${1$$classname$$}$ : int {\n", descriptor_);
+ format.Indent();
+
+ const EnumValueDescriptor* min_value = descriptor_->value(0);
+ const EnumValueDescriptor* max_value = descriptor_->value(0);
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ auto format_value = format;
+ format_value.Set("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.
+ format_value.Set("number", Int32ToString(descriptor_->value(i)->number()));
+ format_value.Set("deprecation",
+ DeprecatedAttribute(options_, descriptor_->value(i)));
+
+ if (i > 0) format_value(",\n");
+ format_value("${1$$prefix$$name$$}$ $deprecation$= $number$",
+ descriptor_->value(i));
+
+ if (descriptor_->value(i)->number() < min_value->number()) {
+ min_value = descriptor_->value(i);
+ }
+ if (descriptor_->value(i)->number() > max_value->number()) {
+ max_value = descriptor_->value(i);
+ }
+ }
+
+ if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ // For new enum semantics: generate min and max sentinel values equal to
+ // INT32_MIN and INT32_MAX
+ if (descriptor_->value_count() > 0) format(",\n");
+ format(
+ "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = "
+ "std::numeric_limits<$int32$>::min(),\n"
+ "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = "
+ "std::numeric_limits<$int32$>::max()");
+ }
+
+ format.Outdent();
+ format("\n};\n");
+
+ format(
+ "$dllexport_decl $bool $classname$_IsValid(int value);\n"
+ "constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = "
+ "$prefix$$2$;\n"
+ "constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = "
+ "$prefix$$3$;\n",
+ descriptor_, EnumValueName(min_value), EnumValueName(max_value));
+
+ if (generate_array_size_) {
+ format(
+ "constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = "
+ "$prefix$$short_name$_MAX + 1;\n\n",
+ descriptor_);
+ }
+
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
+ "$classname$_descriptor();\n");
+ }
+
+ // The _Name and _Parse functions. The lite implementation is table-based, so
+ // we make sure to keep the tables hidden in the .cc file.
+ if (!HasDescriptorMethods(descriptor_->file(), options_)) {
+ format("const std::string& $classname$_Name($classname$ value);\n");
+ }
+ // The _Name() function accepts the enum type itself but also any integral
+ // type.
+ format(
+ "template<typename T>\n"
+ "inline const std::string& $classname$_Name(T enum_t_value) {\n"
+ " static_assert(::std::is_same<T, $classname$>::value ||\n"
+ " ::std::is_integral<T>::value,\n"
+ " \"Incorrect type passed to function $classname$_Name.\");\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ " return ::$proto_ns$::internal::NameOfEnum(\n"
+ " $classname$_descriptor(), enum_t_value);\n");
+ } else {
+ format(
+ " return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
+ }
+ format("}\n");
+
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "inline bool $classname$_Parse(\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+ "value) "
+ "{\n"
+ " return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
+ " $classname$_descriptor(), name, value);\n"
+ "}\n");
+ } else {
+ format(
+ "bool $classname$_Parse(\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+ "value);\n");
+ }
+}
+
+void EnumGenerator::GenerateGetEnumDescriptorSpecializations(
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format(
+ "template <> struct is_proto_enum< $classtype$> : ::std::true_type "
+ "{};\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "template <>\n"
+ "inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n"
+ " return $classtype$_descriptor();\n"
+ "}\n");
+ }
+}
+
+void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("typedef $classname$ $resolved_name$;\n");
+
+ for (int j = 0; j < descriptor_->value_count(); j++) {
+ std::string deprecated_attr =
+ DeprecatedAttribute(options_, descriptor_->value(j));
+ format(
+ "$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n"
+ " $classname$_$3$;\n",
+ deprecated_attr, descriptor_->value(j),
+ EnumValueName(descriptor_->value(j)));
+ }
+
+ format(
+ "static inline bool $nested_name$_IsValid(int value) {\n"
+ " return $classname$_IsValid(value);\n"
+ "}\n"
+ "static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n"
+ " $classname$_$nested_name$_MIN;\n"
+ "static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n"
+ " $classname$_$nested_name$_MAX;\n",
+ descriptor_);
+ if (generate_array_size_) {
+ format(
+ "static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n"
+ " $classname$_$nested_name$_ARRAYSIZE;\n",
+ descriptor_);
+ }
+
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "static inline const ::$proto_ns$::EnumDescriptor*\n"
+ "$nested_name$_descriptor() {\n"
+ " return $classname$_descriptor();\n"
+ "}\n");
+ }
+
+ format(
+ "template<typename T>\n"
+ "static inline const std::string& $nested_name$_Name(T enum_t_value) {\n"
+ " static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
+ " ::std::is_integral<T>::value,\n"
+ " \"Incorrect type passed to function $nested_name$_Name.\");\n"
+ " return $classname$_Name(enum_t_value);\n"
+ "}\n");
+ format(
+ "static inline bool "
+ "$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
+ " $resolved_name$* value) {\n"
+ " return $classname$_Parse(name, value);\n"
+ "}\n");
+}
+
+void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n"
+ " ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
+ " return $file_level_enum_descriptors$[$1$];\n"
+ "}\n",
+ idx);
+ }
+
+ format(
+ "bool $classname$_IsValid(int 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.
+
+ std::set<int> numbers;
+ for (int j = 0; j < descriptor_->value_count(); j++) {
+ const EnumValueDescriptor* value = descriptor_->value(j);
+ numbers.insert(value->number());
+ }
+
+ for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end();
+ ++iter) {
+ format(" case $1$:\n", Int32ToString(*iter));
+ }
+
+ format(
+ " return true;\n"
+ " default:\n"
+ " return false;\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ if (!HasDescriptorMethods(descriptor_->file(), options_)) {
+ // In lite mode (where descriptors are unavailable), we generate separate
+ // tables for mapping between enum names and numbers. The _entries table
+ // contains the bulk of the data and is sorted by name, while
+ // _entries_by_number is sorted by number and just contains pointers into
+ // _entries. The two tables allow mapping from name to number and number to
+ // name, both in time logarithmic in the number of enum entries. This could
+ // probably be made faster, but for now the tables are intended to be simple
+ // and compact.
+ //
+ // Enums with allow_alias = true support multiple entries with the same
+ // numerical value. In cases where there are multiple names for the same
+ // number, we treat the first name appearing in the .proto file as the
+ // canonical one.
+ std::map<std::string, int> name_to_number;
+ std::map<int, std::string> number_to_canonical_name;
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ name_to_number.emplace(value->name(), value->number());
+ // The same number may appear with multiple names, so we use emplace() to
+ // let the first name win.
+ number_to_canonical_name.emplace(value->number(), value->name());
+ }
+
+ format(
+ "static ::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
+ "$classname$_strings[$1$] = {};\n\n",
+ CountUniqueValues(descriptor_));
+
+ // We concatenate all the names for a given enum into one big string
+ // literal. If instead we store an array of string literals, the linker
+ // seems to put all enum strings for a given .proto file in the same
+ // section, which hinders its ability to strip out unused strings.
+ format("static const char $classname$_names[] =");
+ for (const auto& p : name_to_number) {
+ format("\n \"$1$\"", p.first);
+ }
+ format(";\n\n");
+
+ format(
+ "static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] "
+ "= {\n");
+ int i = 0;
+ std::map<int, int> number_to_index;
+ int data_index = 0;
+ for (const auto& p : name_to_number) {
+ format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index,
+ p.first.size(), p.second);
+ if (number_to_canonical_name[p.second] == p.first) {
+ number_to_index.emplace(p.second, i);
+ }
+ ++i;
+ data_index += p.first.size();
+ }
+
+ format(
+ "};\n"
+ "\n"
+ "static const int $classname$_entries_by_number[] = {\n");
+ for (const auto& p : number_to_index) {
+ format(" $1$, // $2$ -> $3$\n", p.second, p.first,
+ number_to_canonical_name[p.first]);
+ }
+ format(
+ "};\n"
+ "\n");
+
+ format(
+ "const std::string& $classname$_Name(\n"
+ " $classname$ value) {\n"
+ " static const bool dummy =\n"
+ " ::$proto_ns$::internal::InitializeEnumStrings(\n"
+ " $classname$_entries,\n"
+ " $classname$_entries_by_number,\n"
+ " $1$, $classname$_strings);\n"
+ " (void) dummy;\n"
+ " int idx = ::$proto_ns$::internal::LookUpEnumName(\n"
+ " $classname$_entries,\n"
+ " $classname$_entries_by_number,\n"
+ " $1$, value);\n"
+ " return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n"
+ " $classname$_strings[idx].get();\n"
+ "}\n",
+ CountUniqueValues(descriptor_));
+ format(
+ "bool $classname$_Parse(\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+ "value) "
+ "{\n"
+ " int int_value;\n"
+ " bool success = ::$proto_ns$::internal::LookUpEnumValue(\n"
+ " $classname$_entries, $1$, name, &int_value);\n"
+ " if (success) {\n"
+ " *value = static_cast<$classname$>(int_value);\n"
+ " }\n"
+ " return success;\n"
+ "}\n",
+ descriptor_->value_count());
+ }
+
+ if (descriptor_->containing_type() != NULL) {
+ std::string parent = ClassName(descriptor_->containing_type(), false);
+ // Before C++17, we must define the static constants which were
+ // declared in the header, to give the linker a place to put them.
+ // But MSVC++ pre-2015 and post-2017 (version 15.5+) insists that we not.
+ format(
+ "#if (__cplusplus < 201703) && "
+ "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ format("constexpr $classname$ $1$::$2$;\n", parent,
+ EnumValueName(descriptor_->value(i)));
+ }
+ format(
+ "constexpr $classname$ $1$::$nested_name$_MIN;\n"
+ "constexpr $classname$ $1$::$nested_name$_MAX;\n",
+ parent);
+ if (generate_array_size_) {
+ format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent);
+ }
+
+ format(
+ "#endif // (__cplusplus < 201703) && "
+ "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.h
new file mode 100644
index 00000000..19a2cbe5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum.h
@@ -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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+
+#include <map>
+#include <set>
+#include <string>
+#include <compiler/cpp/cpp_options.h>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumGenerator {
+ public:
+ // See generator.cc for the meaning of dllexport_decl.
+ EnumGenerator(const EnumDescriptor* descriptor,
+ const std::map<std::string, std::string>& vars,
+ const Options& options);
+ ~EnumGenerator();
+
+ // 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.
+ void GenerateDefinition(io::Printer* printer);
+
+ // Generate specialization of GetEnumDescriptor<MyEnum>().
+ // Precondition: in ::google::protobuf namespace.
+ void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+
+ // For enums nested within a message, generate code to import all the enum's
+ // symbols (e.g. the enum type name, all its values, etc.) into the class's
+ // namespace. This should be placed inside the class definition in the
+ // header.
+ void GenerateSymbolImports(io::Printer* printer) const;
+
+ // Source file stuff.
+
+ // Generate non-inline methods related to the enum, such as IsValidValue().
+ // Goes in the .cc file. EnumDescriptors are stored in an array, idx is
+ // the index in this array that corresponds with this enum.
+ void GenerateMethods(int idx, io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+ const std::string classname_;
+ const Options& options_;
+ // whether to generate the *_ARRAYSIZE constant.
+ const bool generate_array_size_;
+
+ std::map<std::string, std::string> variables_;
+
+ friend class FileGenerator;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.cc
new file mode 100644
index 00000000..e0b3f9e5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -0,0 +1,406 @@
+// 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 <compiler/cpp/cpp_enum_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
+ const EnumValueDescriptor* default_value = descriptor->default_value_enum();
+ (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
+ (*variables)["default"] = Int32ToString(default_value->number());
+ (*variables)["full_name"] = descriptor->full_name();
+}
+
+} // namespace
+
+// ===================================================================
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(descriptor, options) {
+ SetEnumVariables(descriptor, &variables_, options);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("int $name$_;\n");
+}
+
+void EnumFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
+ "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
+ "private:\n"
+ "$type$ ${1$_internal_$name$$}$() const;\n"
+ "void ${1$_internal_set_$name$$}$($type$ value);\n"
+ "public:\n",
+ descriptor_);
+}
+
+void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$() const {\n"
+ " return static_cast< $type$ >($name$_);\n"
+ "}\n"
+ "inline $type$ $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+ format(" assert($type$_IsValid(value));\n");
+ }
+ format(
+ " $set_hasbit$\n"
+ " $name$_ = value;\n"
+ "}\n"
+ "inline void $classname$::set_$name$($type$ value) {\n"
+ " _internal_set_$name$(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("_internal_set_$name$(from._internal_$name$());\n");
+}
+
+void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("swap($name$_, other->$name$_);\n");
+}
+
+void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = from.$name$_;\n");
+}
+
+void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "target = stream->EnsureSpace(target);\n"
+ "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
+ " $number$, this->_internal_$name$(), target);\n");
+}
+
+void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$ +\n"
+ " "
+ "::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$("
+ "));\n");
+}
+
+void EnumFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_($default$)\n");
+}
+
+// ===================================================================
+
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : EnumFieldGenerator(descriptor, options) {
+ SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
+
+void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$() const {\n"
+ " if (_internal_has_$name$()) {\n"
+ " return static_cast< $type$ >($field_member$);\n"
+ " }\n"
+ " return static_cast< $type$ >($default$);\n"
+ "}\n"
+ "inline $type$ $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+ format(" assert($type$_IsValid(value));\n");
+ }
+ format(
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " }\n"
+ " $field_member$ = value;\n"
+ "}\n"
+ "inline void $classname$::set_$name$($type$ value) {\n"
+ " _internal_set_$name$(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n");
+}
+
+void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$field_member$ = $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 {
+ Formatter format(printer, variables_);
+ format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
+}
+
+// ===================================================================
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(descriptor, options) {
+ SetEnumVariables(descriptor, &variables_, options);
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("::$proto_ns$::RepeatedField<int> $name$_;\n");
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "private:\n"
+ "$type$ ${1$_internal_$name$$}$(int index) const;\n"
+ "void ${1$_internal_add_$name$$}$($type$ value);\n"
+ "::$proto_ns$::RepeatedField<int>* "
+ "${1$_internal_mutable_$name$$}$();\n"
+ "public:\n"
+ "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
+ "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
+ "$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
+ "${1$$name$$}$() const;\n"
+ "$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
+ "${1$mutable_$name$$}$();\n",
+ descriptor_);
+}
+
+void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$(int index) const {\n"
+ " return static_cast< $type$ >($name$_.Get(index));\n"
+ "}\n"
+ "inline $type$ $classname$::$name$(int index) const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$(index);\n"
+ "}\n"
+ "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+ format(" assert($type$_IsValid(value));\n");
+ }
+ format(
+ " $name$_.Set(index, value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::_internal_add_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+ format(" assert($type$_IsValid(value));\n");
+ }
+ format(
+ " $name$_.Add(value);\n"
+ "}\n"
+ "inline void $classname$::add_$name$($type$ value) {\n"
+ " _internal_add_$name$(value);\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ "}\n"
+ "inline const ::$proto_ns$::RepeatedField<int>&\n"
+ "$classname$::$name$() const {\n"
+ "$annotate_list$"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedField<int>*\n"
+ "$classname$::_internal_mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedField<int>*\n"
+ "$classname$::mutable_$name$() {\n"
+ "$annotate_mutable_list$"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ " return _internal_mutable_$name$();\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.Clear();\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSwappingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.InternalSwap(&other->$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ // Not needed for repeated fields.
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (descriptor_->is_packed()) {
+ // Write the tag and the size.
+ format(
+ "{\n"
+ " int byte_size = "
+ "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
+ " if (byte_size > 0) {\n"
+ " target = stream->WriteEnumPacked(\n"
+ " $number$, $name$_, byte_size, target);\n"
+ " }\n"
+ "}\n");
+ } else {
+ format(
+ "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
+ " target = stream->EnsureSpace(target);\n"
+ " target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
+ " $number$, this->_internal_$name$(i), target);\n"
+ "}\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "{\n"
+ " size_t data_size = 0;\n"
+ " unsigned int count = static_cast<unsigned "
+ "int>(this->_internal_$name$_size());");
+ format.Indent();
+ format(
+ "for (unsigned int i = 0; i < count; i++) {\n"
+ " data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n"
+ " this->_internal_$name$(static_cast<int>(i)));\n"
+ "}\n");
+
+ if (descriptor_->is_packed()) {
+ format(
+ "if (data_size > 0) {\n"
+ " total_size += $tag_size$ +\n"
+ " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
+ " static_cast<$int32$>(data_size));\n"
+ "}\n"
+ "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
+ "_$name$_cached_byte_size_.store(cached_size,\n"
+ " std::memory_order_relaxed);\n"
+ "total_size += data_size;\n");
+ } else {
+ format("total_size += ($tag_size$UL * count) + data_size;\n");
+ }
+ format.Outdent();
+ format("}\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_()");
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("\n, _$name$_cached_byte_size_(0)");
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.h
new file mode 100644
index 00000000..3be207bf
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_enum_field.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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumFieldGenerator : public FieldGenerator {
+ public:
+ EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+ ~EnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ 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) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public FieldGenerator {
+ public:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ ~RepeatedEnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.cc
new file mode 100644
index 00000000..f0dae72d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.cc
@@ -0,0 +1,189 @@
+// 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 <compiler/cpp/cpp_extension.h>
+#include <map>
+#include <compiler/cpp/cpp_helpers.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : descriptor_(descriptor), options_(options), scc_analyzer_(scc_analyzer) {
+ // Construct type_traits_.
+ if (descriptor_->is_repeated()) {
+ type_traits_ = "Repeated";
+ }
+
+ switch (descriptor_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ type_traits_.append("EnumTypeTraits< ");
+ type_traits_.append(ClassName(descriptor_->enum_type(), true));
+ type_traits_.append(", ");
+ type_traits_.append(ClassName(descriptor_->enum_type(), true));
+ type_traits_.append("_IsValid>");
+ break;
+ case FieldDescriptor::CPPTYPE_STRING:
+ type_traits_.append("StringTypeTraits");
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ type_traits_.append("MessageTypeTraits< ");
+ type_traits_.append(ClassName(descriptor_->message_type(), true));
+ type_traits_.append(" >");
+ break;
+ default:
+ type_traits_.append("PrimitiveTypeTraits< ");
+ type_traits_.append(PrimitiveTypeName(options_, descriptor_->cpp_type()));
+ type_traits_.append(" >");
+ break;
+ }
+ SetCommonVars(options, &variables_);
+ variables_["extendee"] =
+ QualifiedClassName(descriptor_->containing_type(), options_);
+ variables_["type_traits"] = type_traits_;
+ std::string name = descriptor_->name();
+ variables_["name"] = ResolveKeyword(name);
+ variables_["constant_name"] = FieldConstantName(descriptor_);
+ variables_["field_type"] =
+ StrCat(static_cast<int>(descriptor_->type()));
+ variables_["packed"] = descriptor_->is_packed() ? "true" : "false";
+
+ std::string scope =
+ IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : "";
+ variables_["scope"] = scope;
+ variables_["scoped_name"] = ExtensionName(descriptor_);
+ variables_["number"] = StrCat(descriptor_->number());
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+bool ExtensionGenerator::IsScoped() const {
+ return descriptor_->extension_scope() != nullptr;
+}
+
+void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+
+ // If this is a class member, it needs to be declared "static". Otherwise,
+ // it needs to be "extern". In the latter case, it also needs the DLL
+ // export/import specifier.
+ std::string qualifier;
+ if (!IsScoped()) {
+ qualifier = "extern";
+ if (!options_.dllexport_decl.empty()) {
+ qualifier = options_.dllexport_decl + " " + qualifier;
+ }
+ } else {
+ qualifier = "static";
+ }
+
+ format(
+ "static const int $constant_name$ = $number$;\n"
+ "$1$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
+ " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " ${2$$name$$}$;\n",
+ qualifier, descriptor_);
+}
+
+void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
+ // If we are building for lite with implicit weak fields, we want to skip over
+ // any custom options (i.e. extensions of messages from descriptor.proto).
+ // This prevents the creation of any unnecessary linker references to the
+ // descriptor messages.
+ if (options_.lite_implicit_weak_fields &&
+ descriptor_->containing_type()->file()->name() ==
+ "net/proto2/proto/descriptor.proto") {
+ return;
+ }
+
+ Formatter format(printer, variables_);
+ std::string default_str;
+ // If this is a class member, it needs to be declared in its class scope.
+ if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ // We need to declare a global string which will contain the default value.
+ // We cannot declare it at class scope because that would require exposing
+ // it in the header which would be annoying for other reasons. So we
+ // replace :: with _ in the name and declare it as a global.
+ default_str =
+ StringReplace(variables_["scoped_name"], "::", "_", true) + "_default";
+ format("const std::string $1$($2$);\n", default_str,
+ DefaultValue(options_, descriptor_));
+ } else if (descriptor_->message_type()) {
+ // We have to initialize the default instance for extensions at registration
+ // time.
+ default_str =
+ FieldMessageTypeName(descriptor_, options_) + "::default_instance()";
+ } else {
+ default_str = DefaultValue(options_, descriptor_);
+ }
+
+ // Likewise, class members need to declare the field constant variable.
+ if (IsScoped()) {
+ format(
+ "#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)\n"
+ "const int $scope$$constant_name$;\n"
+ "#endif\n");
+ }
+
+ format(
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
+ "::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n"
+ " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " $scoped_name$($constant_name$, $1$);\n",
+ default_str);
+
+ // Register extension verify function if needed.
+ if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ ShouldVerify(descriptor_->message_type(), options_, scc_analyzer_) &&
+ ShouldVerify(descriptor_->containing_type(), options_, scc_analyzer_)) {
+ format(
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
+ "::$proto_ns$::internal::RegisterExtensionVerify< $extendee$,\n"
+ " $1$, $number$> $2$_$name$_register;\n",
+ ClassName(descriptor_->message_type(), true),
+ IsScoped() ? ClassName(descriptor_->extension_scope(), false) : "");
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.h
new file mode 100644
index 00000000..76c0e3db
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_extension.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
+
+#include <map>
+#include <string>
+
+#include <stubs/common.h>
+#include <compiler/cpp/cpp_options.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MessageSCCAnalyzer;
+
+// Generates code for an extension, which may be within the scope of some
+// message or may be at file scope. This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ExtensionGenerator {
+ public:
+ // See generator.cc for the meaning of dllexport_decl.
+ explicit ExtensionGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~ExtensionGenerator();
+
+ // Header stuff.
+ void GenerateDeclaration(io::Printer* printer) const;
+
+ // Source file stuff.
+ void GenerateDefinition(io::Printer* printer);
+
+ bool IsScoped() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::string type_traits_;
+ Options options_;
+ MessageSCCAnalyzer* scc_analyzer_;
+
+ std::map<std::string, std::string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.cc
new file mode 100644
index 00000000..8edda0c7
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.cc
@@ -0,0 +1,391 @@
+// 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 <compiler/cpp/cpp_field.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_primitive_field.h>
+#include <compiler/cpp/cpp_string_field.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/cpp/cpp_enum_field.h>
+#include <compiler/cpp/cpp_map_field.h>
+#include <compiler/cpp/cpp_message_field.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormat;
+
+namespace {
+
+void MaySetAnnotationVariable(const Options& options,
+ StringPiece annotation_name,
+ StringPiece substitute_template_prefix,
+ StringPiece prepared_template,
+ int field_index, StringPiece access_type,
+ std::map<std::string, std::string>* variables) {
+ if (options.field_listener_options.forbidden_field_listener_events.count(
+ std::string(annotation_name)))
+ return;
+ (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute(
+ StrCat(substitute_template_prefix, prepared_template, ");\n"),
+ field_index, access_type);
+}
+
+std::string GenerateTemplateForOneofString(const FieldDescriptor* descriptor,
+ StringPiece proto_ns,
+ StringPiece field_member) {
+ std::string field_name = google::protobuf::compiler::cpp::FieldName(descriptor);
+ std::string field_pointer =
+ descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+ ? "$0.GetPointer()"
+ : "$0";
+
+ if (descriptor->default_value_string().empty()) {
+ return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
+ field_pointer, ": nullptr"),
+ field_member);
+ }
+
+ if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
+ return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
+ field_pointer, ": nullptr"),
+ field_member);
+ }
+
+ std::string default_value_pointer =
+ descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+ ? "&$1.get()"
+ : "&$1";
+ return strings::Substitute(
+ StrCat("_internal_has_", field_name, "() ? ", field_pointer, " : ",
+ default_value_pointer),
+ field_member, MakeDefaultName(descriptor));
+}
+
+std::string GenerateTemplateForSingleString(const FieldDescriptor* descriptor,
+ StringPiece field_member) {
+ if (descriptor->default_value_string().empty()) {
+ return StrCat("&", field_member);
+ }
+
+ if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) {
+ return strings::Substitute(
+ "$0.IsDefault(nullptr) ? &$1.get() : $0.GetPointer()", field_member,
+ MakeDefaultName(descriptor));
+ }
+
+ return StrCat("&", field_member);
+}
+
+} // namespace
+
+void AddAccessorAnnotations(const FieldDescriptor* descriptor,
+ const Options& options,
+ std::map<std::string, std::string>* variables) {
+ // Can be expanded to include more specific calls, for example, for arena or
+ // clear calls.
+ static constexpr const char* kAccessorsAnnotations[] = {
+ "annotate_add", "annotate_get", "annotate_has",
+ "annotate_list", "annotate_mutable", "annotate_mutable_list",
+ "annotate_release", "annotate_set", "annotate_size",
+ "annotate_clear", "annotate_add_mutable",
+ };
+ for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+ (*variables)[kAccessorsAnnotations[i]] = "";
+ }
+ if (options.annotate_accessor) {
+ for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+ (*variables)[kAccessorsAnnotations[i]] = StrCat(
+ " ", FieldName(descriptor), "_AccessedNoStrip = true;\n");
+ }
+ }
+ if (!options.field_listener_options.inject_field_listener_events) {
+ return;
+ }
+ if (descriptor->file()->options().optimize_for() ==
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ return;
+ }
+ std::string field_member = (*variables)["field_member"];
+ const google::protobuf::OneofDescriptor* oneof_member =
+ descriptor->real_containing_oneof();
+ if (oneof_member) {
+ field_member = StrCat(oneof_member->name(), "_.", field_member);
+ }
+ const std::string proto_ns = (*variables)["proto_ns"];
+ const std::string substitute_template_prefix = " _tracker_.$1<$0>(this, ";
+ std::string prepared_template;
+
+ // Flat template is needed if the prepared one is introspecting the values
+ // inside the returned values, for example, for repeated fields and maps.
+ std::string prepared_flat_template;
+ std::string prepared_add_template;
+ // TODO(b/190614678): Support fields with type Message or Map.
+ if (descriptor->is_repeated() && !descriptor->is_map()) {
+ if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+ prepared_template = strings::Substitute("&$0.Get(index)", field_member);
+ prepared_add_template =
+ strings::Substitute("&$0.Get($0.size() - 1)", field_member);
+ } else {
+ prepared_template = "nullptr";
+ prepared_add_template = "nullptr";
+ }
+ } else if (descriptor->is_map()) {
+ prepared_template = "nullptr";
+ } else if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+ !descriptor->options().lazy()) {
+ prepared_template = "nullptr";
+ } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ if (oneof_member) {
+ prepared_template = GenerateTemplateForOneofString(
+ descriptor, (*variables)["proto_ns"], field_member);
+ } else {
+ prepared_template =
+ GenerateTemplateForSingleString(descriptor, field_member);
+ }
+ } else {
+ prepared_template = StrCat("&", field_member);
+ }
+ if (descriptor->is_repeated() && !descriptor->is_map() &&
+ descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+ prepared_flat_template = StrCat("&", field_member);
+ } else {
+ prepared_flat_template = prepared_template;
+ }
+
+ MaySetAnnotationVariable(options, "get", substitute_template_prefix,
+ prepared_template, descriptor->index(), "OnGet",
+ variables);
+ MaySetAnnotationVariable(options, "set", substitute_template_prefix,
+ prepared_template, descriptor->index(), "OnSet",
+ variables);
+ MaySetAnnotationVariable(options, "has", substitute_template_prefix,
+ prepared_template, descriptor->index(), "OnHas",
+ variables);
+ MaySetAnnotationVariable(options, "mutable", substitute_template_prefix,
+ prepared_template, descriptor->index(), "OnMutable",
+ variables);
+ MaySetAnnotationVariable(options, "release", substitute_template_prefix,
+ prepared_template, descriptor->index(), "OnRelease",
+ variables);
+ MaySetAnnotationVariable(options, "clear", substitute_template_prefix,
+ prepared_flat_template, descriptor->index(),
+ "OnClear", variables);
+ MaySetAnnotationVariable(options, "size", substitute_template_prefix,
+ prepared_flat_template, descriptor->index(),
+ "OnSize", variables);
+ MaySetAnnotationVariable(options, "list", substitute_template_prefix,
+ prepared_flat_template, descriptor->index(),
+ "OnList", variables);
+ MaySetAnnotationVariable(options, "mutable_list", substitute_template_prefix,
+ prepared_flat_template, descriptor->index(),
+ "OnMutableList", variables);
+ MaySetAnnotationVariable(options, "add", substitute_template_prefix,
+ prepared_add_template, descriptor->index(), "OnAdd",
+ variables);
+ MaySetAnnotationVariable(options, "add_mutable", substitute_template_prefix,
+ prepared_add_template, descriptor->index(),
+ "OnAddMutable", variables);
+}
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables,
+ const Options& options) {
+ SetCommonVars(options, variables);
+ (*variables)["ns"] = Namespace(descriptor, options);
+ (*variables)["name"] = FieldName(descriptor);
+ (*variables)["index"] = StrCat(descriptor->index());
+ (*variables)["number"] = StrCat(descriptor->number());
+ (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
+ (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
+ (*variables)["field_member"] = FieldName(descriptor) + "_";
+
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
+
+ (*variables)["set_hasbit"] = "";
+ (*variables)["clear_hasbit"] = "";
+ if (HasHasbit(descriptor)) {
+ (*variables)["set_hasbit_io"] =
+ "_Internal::set_has_" + FieldName(descriptor) + "(&_has_bits_);";
+ } else {
+ (*variables)["set_hasbit_io"] = "";
+ }
+
+ AddAccessorAnnotations(descriptor, options, variables);
+
+ // These variables are placeholders to pick out the beginning and ends of
+ // identifiers for annotations (when doing so with existing variables would
+ // be ambiguous or impossible). They should never be set to anything but the
+ // empty string.
+ (*variables)["{"] = "";
+ (*variables)["}"] = "";
+}
+
+void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
+ if (!HasHasbit(descriptor_)) {
+ GOOGLE_CHECK_EQ(has_bit_index, -1);
+ return;
+ }
+ variables_["set_hasbit"] = StrCat(
+ "_has_bits_[", has_bit_index / 32, "] |= 0x",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+ variables_["clear_hasbit"] = StrCat(
+ "_has_bits_[", has_bit_index / 32, "] &= ~0x",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+}
+
+void FieldGenerator::SetInlinedStringIndex(int32_t inlined_string_index) {
+ if (!IsStringInlined(descriptor_, options_)) {
+ GOOGLE_CHECK_EQ(inlined_string_index, -1);
+ return;
+ }
+ variables_["inlined_string_donated"] = StrCat(
+ "(_inlined_string_donated_[", inlined_string_index / 32, "] & 0x",
+ strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
+ "u) != 0;");
+ variables_["donating_states_word"] =
+ StrCat("_inlined_string_donated_[", inlined_string_index / 32, "]");
+ variables_["mask_for_undonate"] = StrCat(
+ "~0x", strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
+ "u");
+}
+
+void SetCommonOneofFieldVariables(
+ const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ const std::string prefix = descriptor->containing_oneof()->name() + "_.";
+ (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+ (*variables)["field_member"] =
+ StrCat(prefix, (*variables)["name"], "_");
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : descriptor_(descriptor), field_generators_(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, scc_analyzer));
+ }
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator(
+ const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+
+ return nullptr;
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(
+ const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ FieldGenerator* generator =
+ MakeGoogleInternalGenerator(field, options, scc_analyzer);
+ if (generator) {
+ return generator;
+ }
+
+ if (field->is_repeated()) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ if (field->is_map()) {
+ return new MapFieldGenerator(field, options, scc_analyzer);
+ } else {
+ return new RepeatedMessageFieldGenerator(field, options,
+ scc_analyzer);
+ }
+ case FieldDescriptor::CPPTYPE_STRING:
+ return new RepeatedStringFieldGenerator(field, options);
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return new RepeatedEnumFieldGenerator(field, options);
+ default:
+ return new RepeatedPrimitiveFieldGenerator(field, options);
+ }
+ } else if (field->real_containing_oneof()) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return new MessageOneofFieldGenerator(field, options, scc_analyzer);
+ case FieldDescriptor::CPPTYPE_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:
+ return new MessageFieldGenerator(field, options, scc_analyzer);
+ case FieldDescriptor::CPPTYPE_STRING:
+ return new StringFieldGenerator(field, options);
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return new EnumFieldGenerator(field, options);
+ default:
+ return new PrimitiveFieldGenerator(field, options);
+ }
+ }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.h
new file mode 100644
index 00000000..d0ead8c6
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_field.h
@@ -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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_options.h>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Helper function: set variables in the map that are the same for all
+// field code generators.
+// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
+// 'deprecation'].
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables,
+ const Options& options);
+
+void SetCommonOneofFieldVariables(
+ const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables);
+
+class FieldGenerator {
+ public:
+ explicit FieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : descriptor_(descriptor), options_(options) {}
+ virtual ~FieldGenerator();
+ virtual void GenerateSerializeWithCachedSizes(
+ io::Printer* printer) const final{};
+ // Generate lines of code declaring members fields of the message class
+ // needed to represent this field. These are placed inside the message
+ // 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 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 accessor functions for this field.
+ // These are placed inside the header after all class definitions.
+ virtual void GenerateInlineAccessorDefinitions(
+ io::Printer* printer) 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 {}
+
+ // Generate declarations of accessors that are for internal purposes only.
+ // Most field types don't need this, so the default implementation is empty.
+ virtual void GenerateInternalAccessorDefinitions(
+ io::Printer* /*printer*/) const {}
+
+ // Generate definitions of accessors that are for internal purposes only.
+ // Most field types don't need this, so the default implementation is empty.
+ virtual void GenerateInternalAccessorDeclarations(
+ io::Printer* /*printer*/) const {}
+
+ // Generate lines of code (statements, not declarations) which clear the
+ // 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".
+ // This is used to fill in the MergeFrom method for the whole message.
+ // Details of this usage can be found in message.cc under the
+ // 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
+ // define the Swap method. Details of usage can be found in
+ // message.cc under the GenerateSwap method.
+ virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
+
+ // Generate initialization code for private members declared by
+ // GeneratePrivateMembers(). These go into the message class's SharedCtor()
+ // method, invoked by each of the generated constructors.
+ virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
+
+ // 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 {}
+
+ // 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 initialization code for private members declared by
+ // GeneratePrivateMembers(), specifically for the constexpr constructor.
+ // These go into the constructor's initializer list and must follow that
+ // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
+ virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
+
+ // Generate lines to serialize this field directly to the array "target",
+ // which are placed within the message's SerializeWithCachedSizesToArray()
+ // method. This must also advance "target" past the written bytes.
+ virtual void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const = 0;
+
+ // Generate lines to compute the serialized size of this field, which
+ // are placed in the message's ByteSize() method.
+ virtual void GenerateByteSize(io::Printer* printer) const = 0;
+
+ // Generates lines to call IsInitialized() for eligible message fields. Non
+ // message fields won't need to override this function.
+ virtual void GenerateIsInitialized(io::Printer* printer) const {}
+
+ virtual bool IsInlined() const { return false; }
+
+ void SetHasBitIndex(int32_t has_bit_index);
+ void SetInlinedStringIndex(int32_t inlined_string_index);
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ const Options& options_;
+ std::map<std::string, std::string> variables_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+ FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~FieldGeneratorMap();
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+
+ void SetHasBitIndices(const std::vector<int>& has_bit_indices_) {
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ field_generators_[i]->SetHasBitIndex(has_bit_indices_[i]);
+ }
+ }
+
+ void SetInlinedStringIndices(const std::vector<int>& inlined_string_indices) {
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ field_generators_[i]->SetInlinedStringIndex(inlined_string_indices[i]);
+ }
+ }
+
+ private:
+ const Descriptor* descriptor_;
+ std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
+
+ static FieldGenerator* MakeGoogleInternalGenerator(
+ const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.cc
new file mode 100644
index 00000000..51758b9e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.cc
@@ -0,0 +1,1419 @@
+// 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 <compiler/cpp/cpp_file.h>
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <compiler/cpp/cpp_enum.h>
+#include <compiler/cpp/cpp_extension.h>
+#include <compiler/cpp/cpp_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_message.h>
+#include <compiler/cpp/cpp_service.h>
+#include <compiler/scc.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+// Must be last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+// When we forward-declare things, we want to create a sorted order so our
+// output is deterministic and minimizes namespace changes.
+template <class T>
+std::string GetSortKey(const T& val) {
+ return val.full_name();
+}
+
+template <>
+std::string GetSortKey<FileDescriptor>(const FileDescriptor& val) {
+ return val.name();
+}
+
+template <class T>
+bool CompareSortKeys(const T* a, const T* b) {
+ return GetSortKey(*a) < GetSortKey(*b);
+}
+
+template <class T>
+std::vector<const T*> Sorted(const std::unordered_set<const T*>& vals) {
+ std::vector<const T*> sorted(vals.begin(), vals.end());
+ std::sort(sorted.begin(), sorted.end(), CompareSortKeys<T>);
+ return sorted;
+}
+
+} // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
+ : file_(file), options_(options), scc_analyzer_(options) {
+ // These variables are the same on a file level
+ SetCommonVars(options, &variables_);
+ variables_["dllexport_decl"] = options.dllexport_decl;
+ variables_["tablename"] = UniqueName("TableStruct", file_, options_);
+ variables_["file_level_metadata"] =
+ UniqueName("file_level_metadata", file_, options_);
+ variables_["desc_table"] = DescriptorTableName(file_, options_);
+ variables_["file_level_enum_descriptors"] =
+ UniqueName("file_level_enum_descriptors", file_, options_);
+ variables_["file_level_service_descriptors"] =
+ UniqueName("file_level_service_descriptors", file_, options_);
+ variables_["filename"] = file_->name();
+ variables_["package_ns"] = Namespace(file_, options);
+
+ std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
+ for (int i = 0; i < msgs.size(); i++) {
+ // Deleted in destructor
+ MessageGenerator* msg_gen =
+ new MessageGenerator(msgs[i], variables_, i, options, &scc_analyzer_);
+ message_generators_.emplace_back(msg_gen);
+ msg_gen->AddGenerators(&enum_generators_, &extension_generators_);
+ }
+
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ enum_generators_.emplace_back(
+ new EnumGenerator(file->enum_type(i), variables_, options));
+ }
+
+ for (int i = 0; i < file->service_count(); i++) {
+ service_generators_.emplace_back(
+ new ServiceGenerator(file->service(i), variables_, options));
+ }
+ if (HasGenericServices(file_, options_)) {
+ for (int i = 0; i < service_generators_.size(); i++) {
+ service_generators_[i]->index_in_metadata_ = i;
+ }
+ }
+ for (int i = 0; i < file->extension_count(); i++) {
+ extension_generators_.emplace_back(
+ new ExtensionGenerator(file->extension(i), options, &scc_analyzer_));
+ }
+ for (int i = 0; i < file->weak_dependency_count(); ++i) {
+ weak_deps_.insert(file->weak_dependency(i));
+ }
+}
+
+FileGenerator::~FileGenerator() = default;
+
+void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // Only do this for protobuf's own types. There are some google3 protos using
+ // macros as field names and the generated code compiles after the macro
+ // expansion. Undefing these macros actually breaks such code.
+ if (file_->name() != "net/proto2/compiler/proto/plugin.proto" &&
+ file_->name() != "google/protobuf/compiler/plugin.proto") {
+ return;
+ }
+ std::vector<std::string> names_to_undef;
+ std::vector<const FieldDescriptor*> fields;
+ ListAllFields(file_, &fields);
+ for (int i = 0; i < fields.size(); i++) {
+ const std::string& name = fields[i]->name();
+ static const char* kMacroNames[] = {"major", "minor"};
+ for (int j = 0; j < GOOGLE_ARRAYSIZE(kMacroNames); ++j) {
+ if (name == kMacroNames[j]) {
+ names_to_undef.push_back(name);
+ break;
+ }
+ }
+ }
+ for (int i = 0; i < names_to_undef.size(); ++i) {
+ format(
+ "#ifdef $1$\n"
+ "#undef $1$\n"
+ "#endif\n",
+ names_to_undef[i]);
+ }
+}
+
+void FileGenerator::GenerateHeader(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ // port_def.inc must be included after all other includes.
+ IncludeFile("net/proto2/public/port_def.inc", printer);
+ format("#define $1$$ dllexport_decl$\n", FileDllExport(file_, options_));
+ GenerateMacroUndefs(printer);
+
+ // For Any support with lite protos, we need to friend AnyMetadata, so we
+ // forward-declare it here.
+ format(
+ "PROTOBUF_NAMESPACE_OPEN\n"
+ "namespace internal {\n"
+ "class AnyMetadata;\n"
+ "} // namespace internal\n"
+ "PROTOBUF_NAMESPACE_CLOSE\n");
+
+ GenerateGlobalStateFunctionDeclarations(printer);
+
+ GenerateForwardDeclarations(printer);
+
+ {
+ NamespaceOpener ns(Namespace(file_, options_), format);
+
+ format("\n");
+
+ GenerateEnumDefinitions(printer);
+
+ format(kThickSeparator);
+ format("\n");
+
+ GenerateMessageDefinitions(printer);
+
+ format("\n");
+ format(kThickSeparator);
+ format("\n");
+
+ GenerateServiceDefinitions(printer);
+
+ GenerateExtensionIdentifiers(printer);
+
+ format("\n");
+ format(kThickSeparator);
+ format("\n");
+
+ GenerateInlineFunctionDefinitions(printer);
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n"
+ "\n");
+ }
+
+ // We need to specialize some templates in the ::google::protobuf namespace:
+ GenerateProto2NamespaceEnumSpecializations(printer);
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+ IncludeFile("net/proto2/public/port_undef.inc", printer);
+}
+
+void FileGenerator::GenerateProtoHeader(io::Printer* printer,
+ const std::string& info_path) {
+ Formatter format(printer, variables_);
+ if (!options_.proto_h) {
+ return;
+ }
+
+ GenerateTopHeaderGuard(printer, false);
+
+ if (!options_.opensource_runtime) {
+ format(
+ "#ifdef SWIG\n"
+ "#error \"Do not SWIG-wrap protobufs.\"\n"
+ "#endif // SWIG\n"
+ "\n");
+ }
+
+ if (IsBootstrapProto(options_, file_)) {
+ format("// IWYU pragma: private, include \"$1$.proto.h\"\n\n",
+ StripProto(file_->name()));
+ }
+
+ GenerateLibraryIncludes(printer);
+
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ const FileDescriptor* dep = file_->public_dependency(i);
+ format("#include \"$1$.proto.h\"\n", StripProto(dep->name()));
+ }
+
+ format("// @@protoc_insertion_point(includes)\n");
+
+ GenerateMetadataPragma(printer, info_path);
+
+ GenerateHeader(printer);
+
+ GenerateBottomHeaderGuard(printer, false);
+}
+
+void FileGenerator::GeneratePBHeader(io::Printer* printer,
+ const std::string& info_path) {
+ Formatter format(printer, variables_);
+ GenerateTopHeaderGuard(printer, true);
+
+ if (options_.proto_h) {
+ std::string target_basename = StripProto(file_->name());
+ if (!options_.opensource_runtime) {
+ GetBootstrapBasename(options_, target_basename, &target_basename);
+ }
+ format("#include \"$1$.proto.h\" // IWYU pragma: export\n",
+ target_basename);
+ } else {
+ GenerateLibraryIncludes(printer);
+ }
+
+ if (options_.transitive_pb_h) {
+ GenerateDependencyIncludes(printer);
+ }
+
+ // This is unfortunately necessary for some plugins. I don't see why we
+ // need two of the same insertion points.
+ // TODO(gerbens) remove this.
+ format("// @@protoc_insertion_point(includes)\n");
+
+ GenerateMetadataPragma(printer, info_path);
+
+ if (!options_.proto_h) {
+ GenerateHeader(printer);
+ } else {
+ {
+ NamespaceOpener ns(Namespace(file_, options_), format);
+ format(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ }
+ format(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+ }
+
+ GenerateBottomHeaderGuard(printer, true);
+}
+
+void FileGenerator::DoIncludeFile(const std::string& google3_name,
+ bool do_export, io::Printer* printer) {
+ Formatter format(printer, variables_);
+ const std::string prefix = "net/proto2/";
+ GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name;
+
+ if (options_.opensource_runtime) {
+ std::string path = google3_name.substr(prefix.size());
+
+ path = StringReplace(path, "internal/", "", false);
+ path = StringReplace(path, "proto/", "", false);
+ path = StringReplace(path, "public/", "", false);
+ if (options_.runtime_include_base.empty()) {
+ format("#include <$1$>", path);
+ } else {
+ format("#include \"$1$google/protobuf/$2$\"",
+ options_.runtime_include_base, path);
+ }
+ } else {
+ format("#include \"$1$\"", google3_name);
+ }
+
+ if (do_export) {
+ format(" // IWYU pragma: export");
+ }
+
+ format("\n");
+}
+
+std::string FileGenerator::CreateHeaderInclude(const std::string& basename,
+ const FileDescriptor* file) {
+ bool use_system_include = false;
+ std::string name = basename;
+
+ if (options_.opensource_runtime) {
+ if (IsWellKnownMessage(file)) {
+ if (options_.runtime_include_base.empty()) {
+ use_system_include = true;
+ } else {
+ name = options_.runtime_include_base + basename;
+ }
+ }
+ }
+
+ std::string left = "\"";
+ std::string right = "\"";
+ if (use_system_include) {
+ left = "<";
+ right = ">";
+ }
+ return left + name + right;
+}
+
+void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ std::string target_basename = StripProto(file_->name());
+ if (!options_.opensource_runtime) {
+ GetBootstrapBasename(options_, target_basename, &target_basename);
+ }
+ target_basename += options_.proto_h ? ".proto.h" : ".pb.h";
+ format(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#include $1$\n"
+ "\n"
+ "#include <algorithm>\n" // for swap()
+ "\n",
+ CreateHeaderInclude(target_basename, file_));
+
+ IncludeFile("net/proto2/io/public/coded_stream.h", printer);
+ // TODO(gerbens) This is to include parse_context.h, we need a better way
+ IncludeFile("net/proto2/public/extension_set.h", printer);
+ IncludeFile("net/proto2/public/wire_format_lite.h", printer);
+
+ // Unknown fields implementation in lite mode uses StringOutputStream
+ if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
+ IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", printer);
+ }
+
+ if (HasDescriptorMethods(file_, options_)) {
+ IncludeFile("net/proto2/public/descriptor.h", printer);
+ IncludeFile("net/proto2/public/generated_message_reflection.h", printer);
+ IncludeFile("net/proto2/public/reflection_ops.h", printer);
+ IncludeFile("net/proto2/public/wire_format.h", printer);
+ }
+
+ if (HasGeneratedMethods(file_, options_) &&
+ options_.tctable_mode != Options::kTCTableNever) {
+ IncludeFile("net/proto2/public/generated_message_tctable_impl.h", printer);
+ }
+
+ if (options_.proto_h) {
+ // Use the smaller .proto.h files.
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const FileDescriptor* dep = file_->dependency(i);
+ // Do not import weak deps.
+ if (!options_.opensource_runtime && IsDepWeak(dep)) continue;
+ std::string basename = StripProto(dep->name());
+ if (IsBootstrapProto(options_, file_)) {
+ GetBootstrapBasename(options_, basename, &basename);
+ }
+ format("#include \"$1$.proto.h\"\n", basename);
+ }
+ }
+ if (HasCordFields(file_, options_)) {
+ format(
+ "#include \"third_party/absl/strings/internal/string_constant.h\"\n");
+ }
+
+ format("// @@protoc_insertion_point(includes)\n");
+ IncludeFile("net/proto2/public/port_def.inc", printer);
+
+ // For MSVC builds, we use #pragma init_seg to move the initialization of our
+ // libraries to happen before the user code.
+ // This worksaround the fact that MSVC does not do constant initializers when
+ // required by the standard.
+ format("\nPROTOBUF_PRAGMA_INIT_SEG\n");
+}
+
+void FileGenerator::GenerateSourceDefaultInstance(int idx,
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+ MessageGenerator* generator = message_generators_[idx].get();
+ generator->GenerateConstexprConstructor(printer);
+ // Use a union to disable the destructor of the _instance member.
+ // We can constant initialize, but the object will still have a non-trivial
+ // destructor that we need to elide.
+ format(
+ "struct $1$ {\n"
+ " constexpr $1$()\n"
+ " : _instance(::$proto_ns$::internal::ConstantInitialized{}) {}\n"
+ " ~$1$() {}\n"
+ " union {\n"
+ " $2$ _instance;\n"
+ " };\n"
+ "};\n",
+ DefaultInstanceType(generator->descriptor_, options_),
+ generator->classname_);
+ // NO_DESTROY is not necessary for correctness. The empty destructor is
+ // enough. However, the empty destructor fails to be elided in some
+ // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
+ // there just to improve performance and binary size in these builds.
+ format("PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT $1$ $2$;\n",
+ DefaultInstanceType(generator->descriptor_, options_),
+ DefaultInstanceName(generator->descriptor_, options_));
+
+ for (int i = 0; i < generator->descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = generator->descriptor_->field(i);
+ if (IsStringInlined(field, options_)) {
+ // Force the initialization of the inlined string in the default instance.
+ format(
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY std::true_type "
+ "$1$::_init_inline_$2$_ = "
+ "($3$._instance.$2$_.Init(), std::true_type{});\n",
+ ClassName(generator->descriptor_), FieldName(field),
+ DefaultInstanceName(generator->descriptor_, options_));
+ }
+ }
+
+ if (options_.lite_implicit_weak_fields) {
+ format("$1$* $2$ = &$3$;\n",
+ DefaultInstanceType(generator->descriptor_, options_),
+ DefaultInstancePtr(generator->descriptor_, options_),
+ DefaultInstanceName(generator->descriptor_, options_));
+ }
+}
+
+// A list of things defined in one .pb.cc file that we need to reference from
+// another .pb.cc file.
+struct FileGenerator::CrossFileReferences {
+ // Populated if we are referencing from messages or files.
+ std::unordered_set<const Descriptor*> weak_default_instances;
+
+ // Only if we are referencing from files.
+ std::unordered_set<const FileDescriptor*> strong_reflection_files;
+ std::unordered_set<const FileDescriptor*> weak_reflection_files;
+};
+
+void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field,
+ CrossFileReferences* refs) {
+ const Descriptor* msg = field->message_type();
+ if (msg == nullptr) return;
+
+ if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
+ IsWeak(field, options_)) {
+ refs->weak_default_instances.insert(msg);
+ }
+}
+
+void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file,
+ CrossFileReferences* refs) {
+ ForEachField(file, [this, refs](const FieldDescriptor* field) {
+ GetCrossFileReferencesForField(field, refs);
+ });
+
+ if (!HasDescriptorMethods(file, options_)) return;
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ if (IsDepWeak(dep)) {
+ refs->weak_reflection_files.insert(dep);
+ } else {
+ refs->strong_reflection_files.insert(dep);
+ }
+ }
+}
+
+// Generates references to variables defined in other files.
+void FileGenerator::GenerateInternalForwardDeclarations(
+ const CrossFileReferences& refs, io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ {
+ NamespaceOpener ns(format);
+ for (auto instance : Sorted(refs.weak_default_instances)) {
+ ns.ChangeTo(Namespace(instance, options_));
+ if (options_.lite_implicit_weak_fields) {
+ format("extern $1$ $2$;\n", DefaultInstanceType(instance, options_),
+ DefaultInstanceName(instance, options_));
+ format("__attribute__((weak)) $1$* $2$ = nullptr;\n",
+ DefaultInstanceType(instance, options_),
+ DefaultInstancePtr(instance, options_));
+ } else {
+ format("extern __attribute__((weak)) $1$ $2$;\n",
+ DefaultInstanceType(instance, options_),
+ DefaultInstanceName(instance, options_));
+ }
+ }
+ }
+
+ for (auto file : Sorted(refs.weak_reflection_files)) {
+ format(
+ "extern __attribute__((weak)) const "
+ "::$proto_ns$::internal::DescriptorTable $1$;\n",
+ DescriptorTableName(file, options_));
+ }
+}
+
+void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
+ Formatter format(printer, variables_);
+ GenerateSourceIncludes(printer);
+
+ CrossFileReferences refs;
+ ForEachField(message_generators_[idx]->descriptor_,
+ [this, &refs](const FieldDescriptor* field) {
+ GetCrossFileReferencesForField(field, &refs);
+ });
+ GenerateInternalForwardDeclarations(refs, printer);
+
+ { // package namespace
+ NamespaceOpener ns(Namespace(file_, options_), format);
+
+ // Define default instances
+ GenerateSourceDefaultInstance(idx, printer);
+
+ // Generate classes.
+ format("\n");
+ message_generators_[idx]->GenerateClassMethods(printer);
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ } // end package namespace
+
+ {
+ NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
+ message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
+ }
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* printer) {
+ Formatter format(printer, variables_);
+ GenerateSourceIncludes(printer);
+ NamespaceOpener ns(Namespace(file_, options_), format);
+ extension_generators_[idx]->GenerateDefinition(printer);
+}
+
+void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ GenerateSourceIncludes(printer);
+
+ {
+ GenerateTables(printer);
+
+ // Define the code to initialize reflection. This code uses a global
+ // constructor to register reflection data with the runtime pre-main.
+ if (HasDescriptorMethods(file_, options_)) {
+ GenerateReflectionInitializationCode(printer);
+ }
+ }
+
+ NamespaceOpener ns(Namespace(file_, options_), format);
+
+ // Generate enums.
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->GenerateMethods(i, printer);
+ }
+}
+
+void FileGenerator::GenerateSource(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ GenerateSourceIncludes(printer);
+ CrossFileReferences refs;
+ GetCrossFileReferencesForFile(file_, &refs);
+ GenerateInternalForwardDeclarations(refs, printer);
+
+ {
+ NamespaceOpener ns(Namespace(file_, options_), format);
+
+ // Define default instances
+ for (int i = 0; i < message_generators_.size(); i++) {
+ GenerateSourceDefaultInstance(i, printer);
+ }
+ }
+
+ {
+ GenerateTables(printer);
+
+ if (HasDescriptorMethods(file_, options_)) {
+ // Define the code to initialize reflection. This code uses a global
+ // constructor to register reflection data with the runtime pre-main.
+ GenerateReflectionInitializationCode(printer);
+ }
+ }
+
+ {
+ NamespaceOpener ns(Namespace(file_, options_), format);
+
+ // Actually implement the protos
+
+ // Generate enums.
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->GenerateMethods(i, printer);
+ }
+
+ // Generate classes.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ format("\n");
+ format(kThickSeparator);
+ format("\n");
+ message_generators_[i]->GenerateClassMethods(printer);
+ }
+
+ if (HasGenericServices(file_, options_)) {
+ // Generate services.
+ for (int i = 0; i < service_generators_.size(); i++) {
+ if (i == 0) format("\n");
+ format(kThickSeparator);
+ format("\n");
+ service_generators_[i]->GenerateImplementation(printer);
+ }
+ }
+
+ // Define extensions.
+ for (int i = 0; i < extension_generators_.size(); i++) {
+ extension_generators_[i]->GenerateDefinition(printer);
+ }
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+ }
+
+ {
+ NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->GenerateSourceInProto2Namespace(printer);
+ }
+ }
+
+ format(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+
+ IncludeFile("net/proto2/public/port_undef.inc", printer);
+}
+
+void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ if (!message_generators_.empty()) {
+ format("static ::$proto_ns$::Metadata $file_level_metadata$[$1$];\n",
+ message_generators_.size());
+ }
+ if (!enum_generators_.empty()) {
+ format(
+ "static "
+ "const ::$proto_ns$::EnumDescriptor* "
+ "$file_level_enum_descriptors$[$1$];\n",
+ enum_generators_.size());
+ } else {
+ format(
+ "static "
+ "constexpr ::$proto_ns$::EnumDescriptor const** "
+ "$file_level_enum_descriptors$ = nullptr;\n");
+ }
+ if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
+ format(
+ "static "
+ "const ::$proto_ns$::ServiceDescriptor* "
+ "$file_level_service_descriptors$[$1$];\n",
+ file_->service_count());
+ } else {
+ format(
+ "static "
+ "constexpr ::$proto_ns$::ServiceDescriptor const** "
+ "$file_level_service_descriptors$ = nullptr;\n");
+ }
+
+ if (!message_generators_.empty()) {
+ format(
+ "\n"
+ "const $uint32$ $tablename$::offsets[] "
+ "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
+ format.Indent();
+ std::vector<std::pair<size_t, size_t> > pairs;
+ pairs.reserve(message_generators_.size());
+ for (int i = 0; i < message_generators_.size(); i++) {
+ pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
+ }
+ format.Outdent();
+ format(
+ "};\n"
+ "static const ::$proto_ns$::internal::MigrationSchema schemas[] "
+ "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
+ format.Indent();
+ {
+ int offset = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->GenerateSchema(printer, offset,
+ pairs[i].second);
+ offset += pairs[i].first;
+ }
+ }
+ format.Outdent();
+ format(
+ "};\n"
+ "\nstatic "
+ "::$proto_ns$::Message const * const file_default_instances[] = {\n");
+ format.Indent();
+ for (int i = 0; i < message_generators_.size(); i++) {
+ const Descriptor* descriptor = message_generators_[i]->descriptor_;
+ format(
+ "reinterpret_cast<const "
+ "::$proto_ns$::Message*>(&$1$::_$2$_default_instance_),\n",
+ Namespace(descriptor, options_), // 1
+ ClassName(descriptor)); // 2
+ }
+ format.Outdent();
+ format(
+ "};\n"
+ "\n");
+ } else {
+ // we still need these symbols to exist
+ format(
+ // MSVC doesn't like empty arrays, so we add a dummy.
+ "const $uint32$ $tablename$::offsets[1] = {};\n"
+ "static constexpr ::$proto_ns$::internal::MigrationSchema* schemas = "
+ "nullptr;"
+ "\n"
+ "static constexpr ::$proto_ns$::Message* const* "
+ "file_default_instances = nullptr;\n"
+ "\n");
+ }
+
+ // ---------------------------------------------------------------
+
+ // 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.
+ const std::string protodef_name =
+ UniqueName("descriptor_table_protodef", file_, options_);
+ format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n",
+ protodef_name);
+ format.Indent();
+ FileDescriptorProto file_proto;
+ file_->CopyTo(&file_proto);
+ std::string file_data;
+ file_proto.SerializeToString(&file_data);
+
+ {
+ if (file_data.size() > 65535) {
+ // Workaround for MSVC: "Error C1091: compiler limit: string exceeds
+ // 65535 bytes in length". Declare a static array of chars rather than
+ // use a string literal. Only write 25 bytes per line.
+ static const int kBytesPerLine = 25;
+ format("{ ");
+ for (int i = 0; i < file_data.size();) {
+ for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
+ format("'$1$', ", CEscape(file_data.substr(i, 1)));
+ }
+ format("\n");
+ }
+ format("'\\0' }"); // null-terminate
+ } else {
+ // Only write 40 bytes per line.
+ static const int kBytesPerLine = 40;
+ for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+ format(
+ "\"$1$\"\n",
+ EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+ }
+ }
+ format(";\n");
+ }
+ format.Outdent();
+
+ CrossFileReferences refs;
+ GetCrossFileReferencesForFile(file_, &refs);
+ int num_deps =
+ refs.strong_reflection_files.size() + refs.weak_reflection_files.size();
+
+ // Build array of DescriptorTable deps.
+ if (num_deps > 0) {
+ format(
+ "static const ::$proto_ns$::internal::DescriptorTable*const "
+ "$desc_table$_deps[$1$] = {\n",
+ num_deps);
+
+ for (auto dep : Sorted(refs.strong_reflection_files)) {
+ format(" &::$1$,\n", DescriptorTableName(dep, options_));
+ }
+ for (auto dep : Sorted(refs.weak_reflection_files)) {
+ format(" &::$1$,\n", DescriptorTableName(dep, options_));
+ }
+
+ format("};\n");
+ }
+
+ // The DescriptorTable itself.
+ // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);"
+ // however this might cause a tsan failure in superroot b/148382879,
+ // so disable for now.
+ bool eager = false;
+ format(
+ "static ::$proto_ns$::internal::once_flag $desc_table$_once;\n"
+ "const ::$proto_ns$::internal::DescriptorTable $desc_table$ = {\n"
+ " false, $1$, $2$, $3$, \"$filename$\", \n"
+ " &$desc_table$_once, $4$, $5$, $6$,\n"
+ " schemas, file_default_instances, $tablename$::offsets,\n"
+ " $7$, $file_level_enum_descriptors$, "
+ "$file_level_service_descriptors$,\n"
+ "};\n"
+ // This function exists to be marked as weak.
+ // It can significantly speed up compilation by breaking up LLVM's SCC in
+ // the .pb.cc translation units. Large translation units see a reduction
+ // of more than 35% of walltime for optimized builds.
+ // Without the weak attribute all the messages in the file, including all
+ // the vtables and everything they use become part of the same SCC through
+ // a cycle like:
+ // GetMetadata -> descriptor table -> default instances ->
+ // vtables -> GetMetadata
+ // By adding a weak function here we break the connection from the
+ // individual vtables back into the descriptor table.
+ "PROTOBUF_ATTRIBUTE_WEAK const ::$proto_ns$::internal::DescriptorTable* "
+ "$desc_table$_getter() {\n"
+ " return &$desc_table$;\n"
+ "}\n"
+ "\n",
+ eager ? "true" : "false", file_data.size(), protodef_name,
+ num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps,
+ message_generators_.size(),
+ message_generators_.empty() ? "nullptr"
+ : variables_["file_level_metadata"]);
+
+ // For descriptor.proto we want to avoid doing any dynamic initialization,
+ // because in some situations that would otherwise pull in a lot of
+ // unnecessary code that can't be stripped by --gc-sections. Descriptor
+ // initialization will still be performed lazily when it's needed.
+ if (file_->name() != "net/proto2/proto/descriptor.proto") {
+ format(
+ "// Force running AddDescriptors() at dynamic initialization time.\n"
+ "PROTOBUF_ATTRIBUTE_INIT_PRIORITY "
+ "static ::$proto_ns$::internal::AddDescriptorsRunner "
+ "$1$(&$desc_table$);\n",
+ UniqueName("dynamic_init_dummy", file_, options_));
+ }
+}
+
+void FileGenerator::GenerateTables(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (options_.table_driven_parsing) {
+ // TODO(ckennelly): Gate this with the same options flag to enable
+ // table-driven parsing.
+ format(
+ "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTableField\n"
+ " const $tablename$::entries[] "
+ "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
+ format.Indent();
+
+ std::vector<size_t> entries;
+ size_t count = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ size_t value = message_generators_[i]->GenerateParseOffsets(printer);
+ entries.push_back(value);
+ count += value;
+ }
+
+ // We need these arrays to exist, and MSVC does not like empty arrays.
+ if (count == 0) {
+ format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n");
+ }
+
+ format.Outdent();
+ format(
+ "};\n"
+ "\n"
+ "PROTOBUF_CONSTEXPR_VAR "
+ "::$proto_ns$::internal::AuxiliaryParseTableField\n"
+ " const $tablename$::aux[] "
+ "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
+ format.Indent();
+
+ std::vector<size_t> aux_entries;
+ count = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ size_t value = message_generators_[i]->GenerateParseAuxTable(printer);
+ aux_entries.push_back(value);
+ count += value;
+ }
+
+ if (count == 0) {
+ format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
+ }
+
+ format.Outdent();
+ format(
+ "};\n"
+ "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTable const\n"
+ " $tablename$::schema[] "
+ "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
+ format.Indent();
+
+ size_t offset = 0;
+ size_t aux_offset = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->GenerateParseTable(printer, offset, aux_offset);
+ offset += entries[i];
+ aux_offset += aux_entries[i];
+ }
+
+ if (message_generators_.empty()) {
+ format("{ nullptr, nullptr, 0, -1, -1, false },\n");
+ }
+
+ format.Outdent();
+ format(
+ "};\n"
+ "\n");
+ }
+
+ if (!message_generators_.empty() && options_.table_driven_serialization) {
+ format(
+ "const ::$proto_ns$::internal::FieldMetadata "
+ "$tablename$::field_metadata[] "
+ "= {\n");
+ format.Indent();
+ std::vector<int> field_metadata_offsets;
+ int idx = 0;
+ for (int i = 0; i < message_generators_.size(); i++) {
+ field_metadata_offsets.push_back(idx);
+ idx += message_generators_[i]->GenerateFieldMetadata(printer);
+ }
+ field_metadata_offsets.push_back(idx);
+ format.Outdent();
+ format(
+ "};\n"
+ "const ::$proto_ns$::internal::SerializationTable "
+ "$tablename$::serialization_table[] = {\n");
+ format.Indent();
+ // We rely on the order we layout the tables to match the order we
+ // calculate them with FlattenMessagesInFile, so we check here that
+ // these match exactly.
+ std::vector<const Descriptor*> calculated_order =
+ FlattenMessagesInFile(file_);
+ GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
+ for (int i = 0; i < message_generators_.size(); i++) {
+ GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
+ format("{$1$, $tablename$::field_metadata + $2$},\n",
+ field_metadata_offsets[i + 1] - field_metadata_offsets[i], // 1
+ field_metadata_offsets[i]); // 2
+ }
+ format.Outdent();
+ format(
+ "};\n"
+ "\n");
+ }
+}
+
+class FileGenerator::ForwardDeclarations {
+ public:
+ void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; }
+ void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; }
+
+ void Print(const Formatter& format, const Options& options) const {
+ for (const auto& p : enums_) {
+ const std::string& enumname = p.first;
+ const EnumDescriptor* enum_desc = p.second;
+ format(
+ "enum ${1$$2$$}$ : int;\n"
+ "bool $2$_IsValid(int value);\n",
+ enum_desc, enumname);
+ }
+ for (const auto& p : classes_) {
+ const std::string& classname = p.first;
+ const Descriptor* class_desc = p.second;
+ format(
+ "class ${1$$2$$}$;\n"
+ "struct $3$;\n"
+ "$dllexport_decl $extern $3$ $4$;\n",
+ class_desc, classname, DefaultInstanceType(class_desc, options),
+ DefaultInstanceName(class_desc, options));
+ }
+ }
+
+ void PrintTopLevelDecl(const Formatter& format,
+ const Options& options) const {
+ for (const auto& pair : classes_) {
+ format(
+ "template<> $dllexport_decl $"
+ "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n",
+ QualifiedClassName(pair.second, options));
+ }
+ }
+
+ private:
+ std::map<std::string, const Descriptor*> classes_;
+ std::map<std::string, const EnumDescriptor*> enums_;
+};
+
+static void PublicImportDFS(const FileDescriptor* fd,
+ std::unordered_set<const FileDescriptor*>* fd_set) {
+ for (int i = 0; i < fd->public_dependency_count(); i++) {
+ const FileDescriptor* dep = fd->public_dependency(i);
+ if (fd_set->insert(dep).second) PublicImportDFS(dep, fd_set);
+ }
+}
+
+void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ std::vector<const Descriptor*> classes;
+ std::vector<const EnumDescriptor*> enums;
+
+ FlattenMessagesInFile(file_, &classes); // All messages need forward decls.
+
+ if (options_.proto_h) { // proto.h needs extra forward declarations.
+ // All classes / enums referred to as field members
+ std::vector<const FieldDescriptor*> fields;
+ ListAllFields(file_, &fields);
+ for (int i = 0; i < fields.size(); i++) {
+ classes.push_back(fields[i]->containing_type());
+ classes.push_back(fields[i]->message_type());
+ enums.push_back(fields[i]->enum_type());
+ }
+ ListAllTypesForServices(file_, &classes);
+ }
+
+ // Calculate the set of files whose definitions we get through include.
+ // No need to forward declare types that are defined in these.
+ std::unordered_set<const FileDescriptor*> public_set;
+ PublicImportDFS(file_, &public_set);
+
+ std::map<std::string, ForwardDeclarations> decls;
+ for (int i = 0; i < classes.size(); i++) {
+ const Descriptor* d = classes[i];
+ if (d && !public_set.count(d->file()))
+ decls[Namespace(d, options_)].AddMessage(d);
+ }
+ for (int i = 0; i < enums.size(); i++) {
+ const EnumDescriptor* d = enums[i];
+ if (d && !public_set.count(d->file()))
+ decls[Namespace(d, options_)].AddEnum(d);
+ }
+
+ {
+ NamespaceOpener ns(format);
+ for (const auto& pair : decls) {
+ ns.ChangeTo(pair.first);
+ pair.second.Print(format, options_);
+ }
+ }
+ format("PROTOBUF_NAMESPACE_OPEN\n");
+ for (const auto& pair : decls) {
+ pair.second.PrintTopLevelDecl(format, options_);
+ }
+ format("PROTOBUF_NAMESPACE_CLOSE\n");
+}
+
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, bool pb_h) {
+ Formatter format(printer, variables_);
+ // Generate top of header.
+ format(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#ifndef $1$\n"
+ "#define $1$\n"
+ "\n"
+ "#include <limits>\n"
+ "#include <string>\n",
+ IncludeGuard(file_, pb_h, options_));
+ if (!options_.opensource_runtime && !enum_generators_.empty()) {
+ // Add header to provide std::is_integral for safe Enum_Name() function.
+ format("#include <type_traits>\n");
+ }
+ format("\n");
+}
+
+void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h) {
+ Formatter format(printer, variables_);
+ format("#endif // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n",
+ IncludeGuard(file_, pb_h, options_));
+}
+
+void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (UsingImplicitWeakFields(file_, options_)) {
+ IncludeFile("net/proto2/public/implicit_weak_message.h", printer);
+ }
+ if (HasWeakFields(file_, options_)) {
+ GOOGLE_CHECK(!options_.opensource_runtime);
+ IncludeFile("net/proto2/public/weak_field_map.h", printer);
+ }
+ if (HasLazyFields(file_, options_, &scc_analyzer_)) {
+ GOOGLE_CHECK(!options_.opensource_runtime);
+ IncludeFile("net/proto2/public/lazy_field.h", printer);
+ }
+ if (ShouldVerify(file_, options_, &scc_analyzer_)) {
+ IncludeFile("net/proto2/public/wire_format_verify.h", printer);
+ }
+
+ if (options_.opensource_runtime) {
+ // Verify the protobuf library header version is compatible with the protoc
+ // version before going any further.
+ IncludeFile("net/proto2/public/port_def.inc", printer);
+ format(
+ "#if PROTOBUF_VERSION < $1$\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 $2$ < 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",
+ PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC, // 1
+ PROTOBUF_VERSION); // 2
+ IncludeFile("net/proto2/public/port_undef.inc", printer);
+ }
+
+ // OK, it's now safe to #include other files.
+ IncludeFile("net/proto2/io/public/coded_stream.h", printer);
+ IncludeFile("net/proto2/public/arena.h", printer);
+ IncludeFile("net/proto2/public/arenastring.h", printer);
+ if ((options_.force_inline_string || options_.profile_driven_inline_string) &&
+ !options_.opensource_runtime) {
+ IncludeFile("net/proto2/public/inlined_string_field.h", printer);
+ }
+ if (HasSimpleBaseClasses(file_, options_)) {
+ IncludeFile("net/proto2/public/generated_message_bases.h", printer);
+ }
+ IncludeFile("net/proto2/public/generated_message_table_driven.h", printer);
+ if (HasGeneratedMethods(file_, options_) &&
+ options_.tctable_mode != Options::kTCTableNever) {
+ IncludeFile("net/proto2/public/generated_message_tctable_decl.h", printer);
+ }
+ IncludeFile("net/proto2/public/generated_message_util.h", printer);
+ IncludeFile("net/proto2/public/metadata_lite.h", printer);
+
+ if (HasDescriptorMethods(file_, options_)) {
+ IncludeFile("net/proto2/public/generated_message_reflection.h", printer);
+ }
+
+ if (!message_generators_.empty()) {
+ if (HasDescriptorMethods(file_, options_)) {
+ IncludeFile("net/proto2/public/message.h", printer);
+ } else {
+ IncludeFile("net/proto2/public/message_lite.h", printer);
+ }
+ }
+ if (options_.opensource_runtime) {
+ // Open-source relies on unconditional includes of these.
+ IncludeFileAndExport("net/proto2/public/repeated_field.h", printer);
+ IncludeFileAndExport("net/proto2/public/extension_set.h", printer);
+ } else {
+ // Google3 includes these files only when they are necessary.
+ if (HasExtensionsOrExtendableMessage(file_)) {
+ IncludeFileAndExport("net/proto2/public/extension_set.h", printer);
+ }
+ if (HasRepeatedFields(file_)) {
+ IncludeFileAndExport("net/proto2/public/repeated_field.h", printer);
+ }
+ if (HasStringPieceFields(file_, options_)) {
+ IncludeFile("net/proto2/public/string_piece_field_support.h", printer);
+ }
+ if (HasCordFields(file_, options_)) {
+ format("#include \"third_party/absl/strings/cord.h\"\n");
+ }
+ }
+ if (HasMapFields(file_)) {
+ IncludeFileAndExport("net/proto2/public/map.h", printer);
+ if (HasDescriptorMethods(file_, options_)) {
+ IncludeFile("net/proto2/public/map_entry.h", printer);
+ IncludeFile("net/proto2/public/map_field_inl.h", printer);
+ } else {
+ IncludeFile("net/proto2/public/map_entry_lite.h", printer);
+ IncludeFile("net/proto2/public/map_field_lite.h", printer);
+ }
+ }
+
+ if (HasEnumDefinitions(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
+ IncludeFile("net/proto2/public/generated_enum_reflection.h", printer);
+ } else {
+ IncludeFile("net/proto2/public/generated_enum_util.h", printer);
+ }
+ }
+
+ if (HasGenericServices(file_, options_)) {
+ IncludeFile("net/proto2/public/service.h", printer);
+ }
+
+ if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
+ IncludeFile("net/proto2/public/unknown_field_set.h", printer);
+ }
+}
+
+void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
+ const std::string& info_path) {
+ Formatter format(printer, variables_);
+ if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
+ !options_.annotation_guard_name.empty()) {
+ format.Set("guard", options_.annotation_guard_name);
+ format.Set("pragma", options_.annotation_pragma_name);
+ format.Set("info_path", info_path);
+ format(
+ "#ifdef $guard$\n"
+ "#pragma $pragma$ \"$info_path$\"\n"
+ "#endif // $guard$\n");
+ }
+}
+
+void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ std::string basename = StripProto(file_->dependency(i)->name());
+
+ // Do not import weak deps.
+ if (IsDepWeak(file_->dependency(i))) continue;
+
+ if (IsBootstrapProto(options_, file_)) {
+ GetBootstrapBasename(options_, basename, &basename);
+ }
+
+ format("#include $1$\n",
+ CreateHeaderInclude(basename + ".pb.h", file_->dependency(i)));
+ }
+}
+
+void FileGenerator::GenerateGlobalStateFunctionDeclarations(
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // Forward-declare the DescriptorTable because this is referenced by .pb.cc
+ // files depending on this file.
+ //
+ // The TableStruct is also outputted in weak_message_field.cc, because the
+ // weak fields must refer to table struct but cannot include the header.
+ // Also it annotates extra weak attributes.
+ // TODO(gerbens) make sure this situation is handled better.
+ format(
+ "\n"
+ "// Internal implementation detail -- do not use these members.\n"
+ "struct $dllexport_decl $$tablename$ {\n"
+ // These tables describe how to serialize and parse messages. Used
+ // for table driven code.
+ " static const ::$proto_ns$::internal::ParseTableField entries[]\n"
+ " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
+ " static const ::$proto_ns$::internal::AuxiliaryParseTableField aux[]\n"
+ " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
+ " static const ::$proto_ns$::internal::ParseTable schema[$1$]\n"
+ " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n"
+ " static const ::$proto_ns$::internal::FieldMetadata field_metadata[];\n"
+ " static const ::$proto_ns$::internal::SerializationTable "
+ "serialization_table[];\n"
+ " static const $uint32$ offsets[];\n"
+ "};\n",
+ std::max(size_t(1), message_generators_.size()));
+ if (HasDescriptorMethods(file_, options_)) {
+ format(
+ "$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable "
+ "$desc_table$;\n");
+ }
+}
+
+void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // Generate class definitions.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (i > 0) {
+ format("\n");
+ format(kThinSeparator);
+ format("\n");
+ }
+ message_generators_[i]->GenerateClassDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
+ // Generate enum definitions.
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->GenerateDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (HasGenericServices(file_, options_)) {
+ // Generate service definitions.
+ for (int i = 0; i < service_generators_.size(); i++) {
+ if (i > 0) {
+ format("\n");
+ format(kThinSeparator);
+ format("\n");
+ }
+ service_generators_[i]->GenerateDeclarations(printer);
+ }
+
+ format("\n");
+ format(kThickSeparator);
+ format("\n");
+ }
+}
+
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
+ // Declare extension identifiers. These are in global scope and so only
+ // the global scope extensions.
+ for (auto& extension_generator : extension_generators_) {
+ if (extension_generator->IsScoped()) continue;
+ extension_generator->GenerateDeclaration(printer);
+ }
+}
+
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
+ // of gcc fires a bogus error when compiled with strict-aliasing.
+ format(
+ "#ifdef __GNUC__\n"
+ " #pragma GCC diagnostic push\n"
+ " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"
+ "#endif // __GNUC__\n");
+ // Generate class inline methods.
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (i > 0) {
+ format(kThinSeparator);
+ format("\n");
+ }
+ message_generators_[i]->GenerateInlineMethods(printer);
+ }
+ format(
+ "#ifdef __GNUC__\n"
+ " #pragma GCC diagnostic pop\n"
+ "#endif // __GNUC__\n");
+
+ for (int i = 0; i < message_generators_.size(); i++) {
+ if (i > 0) {
+ format(kThinSeparator);
+ format("\n");
+ }
+ }
+}
+
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // Emit GetEnumDescriptor specializations into google::protobuf namespace:
+ if (HasEnumDefinitions(file_)) {
+ format("\n");
+ {
+ NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
+ format("\n");
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+ }
+ format("\n");
+ }
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.h
new file mode 100644
index 00000000..a5e751aa
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_file.h
@@ -0,0 +1,208 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// 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 <algorithm>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+#include <stubs/common.h>
+#include <compiler/cpp/cpp_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_options.h>
+#include <compiler/scc.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+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 std::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 std::string& info_path);
+ void GenerateSource(io::Printer* printer);
+
+ // The following member functions are used when the lite_implicit_weak_fields
+ // option is set. In this mode the code is organized a bit differently to
+ // promote better linker stripping of unused code. In particular, we generate
+ // one .cc file per message, one .cc file per extension, and a main pb.cc file
+ // containing everything else.
+
+ int NumMessages() const { return message_generators_.size(); }
+ int NumExtensions() const { return extension_generators_.size(); }
+ // Generates the source file for one message.
+ void GenerateSourceForMessage(int idx, io::Printer* printer);
+ // Generates the source file for one extension.
+ void GenerateSourceForExtension(int idx, io::Printer* printer);
+ // Generates a source file containing everything except messages and
+ // extensions.
+ void GenerateGlobalSource(io::Printer* printer);
+
+ private:
+ // Internal type used by GenerateForwardDeclarations (defined in file.cc).
+ class ForwardDeclarations;
+ struct CrossFileReferences;
+
+ void IncludeFile(const std::string& google3_name, io::Printer* printer) {
+ DoIncludeFile(google3_name, false, printer);
+ }
+ void IncludeFileAndExport(const std::string& google3_name,
+ io::Printer* printer) {
+ DoIncludeFile(google3_name, true, printer);
+ }
+ void DoIncludeFile(const std::string& google3_name, bool do_export,
+ io::Printer* printer);
+
+ std::string CreateHeaderInclude(const std::string& basename,
+ const FileDescriptor* file);
+ void GetCrossFileReferencesForField(const FieldDescriptor* field,
+ CrossFileReferences* refs);
+ void GetCrossFileReferencesForFile(const FileDescriptor* file,
+ CrossFileReferences* refs);
+ void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
+ io::Printer* printer);
+ void GenerateSourceIncludes(io::Printer* printer);
+ void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
+
+ void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
+ io::Printer* printer);
+ void GenerateTables(io::Printer* printer);
+ void GenerateReflectionInitializationCode(io::Printer* printer);
+
+ // For other imports, generates their forward-declarations.
+ void GenerateForwardDeclarations(io::Printer* printer);
+
+ // Generates top or bottom of a header file.
+ void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h);
+ void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h);
+
+ // 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 std::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 definitions.
+ void GenerateInlineFunctionDefinitions(io::Printer* printer);
+
+ void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
+
+ // Sometimes the names we use in a .proto file happen to be defined as
+ // macros on some platforms (e.g., macro/minor used in plugin.proto are
+ // defined as macros in sys/types.h on FreeBSD and a few other platforms).
+ // To make the generated code compile on these platforms, we either have to
+ // undef the macro for these few platforms, or rename the field name for all
+ // platforms. Since these names are part of protobuf public API, renaming is
+ // generally a breaking change so we prefer the #undef approach.
+ void GenerateMacroUndefs(io::Printer* printer);
+
+ bool IsDepWeak(const FileDescriptor* dep) const {
+ if (weak_deps_.count(dep) != 0) {
+ GOOGLE_CHECK(!options_.opensource_runtime);
+ return true;
+ }
+ return false;
+ }
+
+ std::set<const FileDescriptor*> weak_deps_;
+
+ const FileDescriptor* file_;
+ const Options options_;
+
+ MessageSCCAnalyzer scc_analyzer_;
+
+ std::map<std::string, std::string> variables_;
+
+ // 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<std::unique_ptr<MessageGenerator>> message_generators_;
+ std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
+ std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
+ std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.cc
new file mode 100644
index 00000000..88caa897
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.cc
@@ -0,0 +1,271 @@
+// 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 <compiler/cpp/cpp_generator.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <stubs/strutil.h>
+#include <compiler/cpp/cpp_file.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+CppGenerator::CppGenerator() {}
+CppGenerator::~CppGenerator() {}
+
+namespace {
+std::string NumberedCcFileName(const std::string& basename, int number) {
+ return StrCat(basename, ".out/", number, ".cc");
+}
+} // namespace
+
+bool CppGenerator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+
+ // -----------------------------------------------------------------
+ // parse generator options
+
+ // If the dllexport_decl option is passed to the compiler, we need to write
+ // it in front of every symbol that should be exported if this .proto is
+ // compiled into a Windows DLL. E.g., if the user invokes the protocol
+ // compiler as:
+ // protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto
+ // then we'll define classes like this:
+ // class FOO_EXPORT Foo {
+ // ...
+ // }
+ // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
+ // __declspec(dllimport) depending on what is being compiled.
+ //
+ Options file_options;
+
+ file_options.opensource_runtime = opensource_runtime_;
+ file_options.runtime_include_base = runtime_include_base_;
+
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "dllexport_decl") {
+ 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 == "speed") {
+ file_options.enforce_mode = EnforceOptimizeMode::kSpeed;
+ } else if (options[i].first == "code_size") {
+ file_options.enforce_mode = EnforceOptimizeMode::kCodeSize;
+ } else if (options[i].first == "lite") {
+ file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
+ } else if (options[i].first == "lite_implicit_weak_fields") {
+ file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
+ file_options.lite_implicit_weak_fields = true;
+ if (!options[i].second.empty()) {
+ file_options.num_cc_files =
+ strto32(options[i].second.c_str(), NULL, 10);
+ }
+ } else if (options[i].first == "annotate_accessor") {
+ file_options.annotate_accessor = true;
+ } else if (options[i].first == "inject_field_listener_events") {
+ file_options.field_listener_options.inject_field_listener_events = true;
+ } else if (options[i].first == "forbidden_field_listener_events") {
+ std::size_t pos = 0;
+ do {
+ std::size_t next_pos = options[i].second.find_first_of("+", pos);
+ if (next_pos == std::string::npos) {
+ next_pos = options[i].second.size();
+ }
+ if (next_pos > pos)
+ file_options.field_listener_options.forbidden_field_listener_events
+ .insert(options[i].second.substr(pos, next_pos - pos));
+ pos = next_pos + 1;
+ } while (pos < options[i].second.size());
+ } else if (options[i].first == "eagerly_verified_lazy") {
+ file_options.eagerly_verified_lazy = true;
+ } else if (options[i].first == "force_eagerly_verified_lazy") {
+ file_options.force_eagerly_verified_lazy = true;
+ } else if (options[i].first == "table_driven_parsing") {
+ file_options.table_driven_parsing = true;
+ } else if (options[i].first == "table_driven_serialization") {
+ file_options.table_driven_serialization = true;
+ } else if (options[i].first == "experimental_tail_call_table_mode") {
+ if (options[i].second == "never") {
+ file_options.tctable_mode = Options::kTCTableNever;
+ } else if (options[i].second == "guarded") {
+ file_options.tctable_mode = Options::kTCTableGuarded;
+ } else if (options[i].second == "always") {
+ file_options.tctable_mode = Options::kTCTableAlways;
+ } else {
+ *error = "Unknown value for experimental_tail_call_table_mode: " +
+ options[i].second;
+ return false;
+ }
+ } else {
+ *error = "Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ // The safe_boundary_check option controls behavior for Google-internal
+ // protobuf APIs.
+ if (file_options.safe_boundary_check && file_options.opensource_runtime) {
+ *error =
+ "The safe_boundary_check option is not supported outside of Google.";
+ return false;
+ }
+
+ // -----------------------------------------------------------------
+
+
+ std::string basename = StripProto(file->name());
+
+ if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap,
+ &basename)) {
+ return true;
+ }
+
+ FileGenerator file_generator(file, file_options);
+
+ // Generate header(s).
+ if (file_options.proto_h) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".proto.h"));
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ std::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) {
+ std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+ generator_context->Open(info_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
+ }
+
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".pb.h"));
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ std::string info_path = basename + ".pb.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) {
+ std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+ generator_context->Open(info_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
+ }
+
+ // Generate cc file(s).
+ if (UsingImplicitWeakFields(file, file_options)) {
+ {
+ // This is the global .cc file, containing
+ // enum/services/tables/reflection
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".pb.cc"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateGlobalSource(&printer);
+ }
+
+ int num_cc_files =
+ file_generator.NumMessages() + file_generator.NumExtensions();
+
+ // If we're using implicit weak fields then we allow the user to
+ // optionally specify how many files to generate, not counting the global
+ // pb.cc file. If we have more files than messages, then some files will
+ // be generated as empty placeholders.
+ if (file_options.num_cc_files > 0) {
+ GOOGLE_CHECK_LE(num_cc_files, file_options.num_cc_files)
+ << "There must be at least as many numbered .cc files as messages "
+ "and extensions.";
+ num_cc_files = file_options.num_cc_files;
+ }
+ int cc_file_number = 0;
+ for (int i = 0; i < file_generator.NumMessages(); i++) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
+ NumberedCcFileName(basename, cc_file_number++)));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSourceForMessage(i, &printer);
+ }
+ for (int i = 0; i < file_generator.NumExtensions(); i++) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
+ NumberedCcFileName(basename, cc_file_number++)));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSourceForExtension(i, &printer);
+ }
+ // Create empty placeholder files if necessary to match the expected number
+ // of files.
+ for (; cc_file_number < num_cc_files; ++cc_file_number) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
+ NumberedCcFileName(basename, cc_file_number)));
+ }
+ } else {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".pb.cc"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSource(&printer);
+ }
+
+ return true;
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.h
new file mode 100644
index 00000000..14c7672a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_generator.h
@@ -0,0 +1,106 @@
+// 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.
+//
+// Generates C++ code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
+
+#include <string>
+#include <compiler/code_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// CodeGenerator implementation which generates a C++ source file and
+// header. If you create your own protocol compiler binary and you want
+// it to support C++ output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT CppGenerator : public CodeGenerator {
+ public:
+ CppGenerator();
+ ~CppGenerator();
+
+ enum class Runtime {
+ kGoogle3, // Use the internal google3 runtime.
+ kOpensource, // Use the open-source runtime.
+
+ // Use the open-source runtime with google3 #include paths. We make these
+ // absolute to avoid ambiguity, so the runtime will be #included like:
+ // #include "third_party/protobuf/.../google/protobuf/message.h"
+ kOpensourceGoogle3
+ };
+
+ void set_opensource_runtime(bool opensource) {
+ opensource_runtime_ = opensource;
+ }
+
+ // If set to a non-empty string, generated code will do:
+ // #include "<BASE>/google/protobuf/message.h"
+ // instead of:
+ // #include <message.h>
+ // This has no effect if opensource_runtime = false.
+ void set_runtime_include_base(const std::string& base) {
+ runtime_include_base_ = base;
+ }
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override {
+ // We don't fully support this yet, but this is needed to unblock the tests,
+ // and we will have full support before the experimental flag is removed.
+ return FEATURE_PROTO3_OPTIONAL;
+ }
+
+ private:
+ bool opensource_runtime_ = true;
+ std::string runtime_include_base_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.cc
new file mode 100644
index 00000000..9f133247
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.cc
@@ -0,0 +1,1497 @@
+// 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 <compiler/cpp/cpp_helpers.h>
+
+#include <cstdint>
+#include <functional>
+#include <limits>
+#include <map>
+#include <queue>
+#include <unordered_set>
+#include <vector>
+
+#include <stubs/common.h>
+#include <stubs/logging.h>
+#include <compiler/cpp/cpp_options.h>
+#include <compiler/cpp/cpp_names.h>
+#include <descriptor.pb.h>
+#include <descriptor.h>
+#include <compiler/scc.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <dynamic_message.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <stubs/hash.h>
+
+// Must be last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+static const char kAnyMessageName[] = "Any";
+static const char kAnyProtoFile[] = "google/protobuf/any.proto";
+
+std::string DotsToColons(const std::string& name) {
+ return StringReplace(name, ".", "::", true);
+}
+
+static const char* const kKeywordList[] = { //
+ "NULL",
+ "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",
+ "nullptr",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_assert",
+ "static_cast",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "thread_local",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq"};
+
+static std::unordered_set<std::string>* MakeKeywordsMap() {
+ auto* result = new std::unordered_set<std::string>();
+ for (const auto keyword : kKeywordList) {
+ result->emplace(keyword);
+ }
+ return result;
+}
+
+static std::unordered_set<std::string>& kKeywords = *MakeKeywordsMap();
+
+std::string IntTypeName(const Options& options, const std::string& type) {
+ return type + "_t";
+}
+
+void SetIntVar(const Options& options, const std::string& type,
+ std::map<std::string, std::string>* variables) {
+ (*variables)[type] = IntTypeName(options, type);
+}
+bool IsEagerlyVerifiedLazyImpl(const FieldDescriptor* field,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return false;
+}
+
+} // namespace
+
+bool IsLazy(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return IsLazilyVerifiedLazy(field, options) ||
+ IsEagerlyVerifiedLazyImpl(field, options, scc_analyzer);
+}
+
+void SetCommonVars(const Options& options,
+ std::map<std::string, std::string>* variables) {
+ (*variables)["proto_ns"] = ProtobufNamespace(options);
+
+ // Warning: there is some clever naming/splitting here to avoid extract script
+ // rewrites. The names of these variables must not be things that the extract
+ // script will rewrite. That's why we use "CHK" (for example) instead of
+ // "GOOGLE_CHECK".
+ if (options.opensource_runtime) {
+ (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF";
+ (*variables)["CHK"] = "GOOGLE_CHECK";
+ (*variables)["DCHK"] = "GOOGLE_DCHECK";
+ } else {
+ // These values are things the extract script would rewrite if we did not
+ // split them. It might not strictly matter since we don't generate google3
+ // code in open-source. But it's good to prevent surprising things from
+ // happening.
+ (*variables)["GOOGLE_PROTOBUF"] =
+ "GOOGLE3"
+ "_PROTOBUF";
+ (*variables)["CHK"] =
+ "CH"
+ "ECK";
+ (*variables)["DCHK"] =
+ "DCH"
+ "ECK";
+ }
+
+ SetIntVar(options, "int8", variables);
+ SetIntVar(options, "uint8", variables);
+ SetIntVar(options, "uint32", variables);
+ SetIntVar(options, "uint64", variables);
+ SetIntVar(options, "int32", variables);
+ SetIntVar(options, "int64", variables);
+ (*variables)["string"] = "std::string";
+}
+
+void SetUnknownFieldsVariable(const Descriptor* descriptor,
+ const Options& options,
+ std::map<std::string, std::string>* variables) {
+ std::string proto_ns = ProtobufNamespace(options);
+ std::string unknown_fields_type;
+ if (UseUnknownFieldSet(descriptor->file(), options)) {
+ unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet";
+ (*variables)["unknown_fields"] =
+ "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" +
+ unknown_fields_type + "::default_instance)";
+ } else {
+ unknown_fields_type =
+ PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING);
+ (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" +
+ unknown_fields_type + ">(::" + proto_ns +
+ "::internal::GetEmptyString)";
+ }
+ (*variables)["unknown_fields_type"] = unknown_fields_type;
+ (*variables)["have_unknown_fields"] =
+ "_internal_metadata_.have_unknown_fields()";
+ (*variables)["mutable_unknown_fields"] =
+ "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type +
+ ">()";
+}
+
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter) {
+ std::string result;
+ // Note: I distrust ctype.h due to locales.
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_next_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ // Capital letters are left as-is.
+ result += input[i];
+ cap_next_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_next_letter = true;
+ } else {
+ cap_next_letter = true;
+ }
+ }
+ return result;
+}
+
+const char kThickSeparator[] =
+ "// ===================================================================\n";
+const char kThinSeparator[] =
+ "// -------------------------------------------------------------------\n";
+
+bool CanInitializeByZeroing(const FieldDescriptor* field) {
+ if (field->is_repeated() || field->is_extension()) return false;
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return field->default_value_enum()->number() == 0;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return field->default_value_int32() == 0;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return field->default_value_int64() == 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return field->default_value_uint32() == 0;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return field->default_value_uint64() == 0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return field->default_value_float() == 0;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return field->default_value_double() == 0;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() == false;
+ default:
+ return false;
+ }
+}
+
+std::string ClassName(const Descriptor* descriptor) {
+ const Descriptor* parent = descriptor->containing_type();
+ std::string res;
+ if (parent) res += ClassName(parent) + "_";
+ res += descriptor->name();
+ if (IsMapEntryMessage(descriptor)) res += "_DoNotUse";
+ return ResolveKeyword(res);
+}
+
+std::string ClassName(const EnumDescriptor* enum_descriptor) {
+ if (enum_descriptor->containing_type() == nullptr) {
+ return ResolveKeyword(enum_descriptor->name());
+ } else {
+ return ClassName(enum_descriptor->containing_type()) + "_" +
+ enum_descriptor->name();
+ }
+}
+
+std::string QualifiedClassName(const Descriptor* d, const Options& options) {
+ return QualifiedFileLevelSymbol(d->file(), ClassName(d), options);
+}
+
+std::string QualifiedClassName(const EnumDescriptor* d,
+ const Options& options) {
+ return QualifiedFileLevelSymbol(d->file(), ClassName(d), options);
+}
+
+std::string QualifiedClassName(const Descriptor* d) {
+ return QualifiedClassName(d, Options());
+}
+
+std::string QualifiedClassName(const EnumDescriptor* d) {
+ return QualifiedClassName(d, Options());
+}
+
+std::string ExtensionName(const FieldDescriptor* d) {
+ if (const Descriptor* scope = d->extension_scope())
+ return StrCat(ClassName(scope), "::", ResolveKeyword(d->name()));
+ return ResolveKeyword(d->name());
+}
+
+std::string QualifiedExtensionName(const FieldDescriptor* d,
+ const Options& options) {
+ GOOGLE_DCHECK(d->is_extension());
+ return QualifiedFileLevelSymbol(d->file(), ExtensionName(d), options);
+}
+
+std::string QualifiedExtensionName(const FieldDescriptor* d) {
+ return QualifiedExtensionName(d, Options());
+}
+
+std::string Namespace(const std::string& package) {
+ if (package.empty()) return "";
+ return "::" + DotsToColons(package);
+}
+
+std::string Namespace(const FileDescriptor* d, const Options& options) {
+ std::string ret = Namespace(d->package());
+ if (IsWellKnownMessage(d) && options.opensource_runtime) {
+ // Written with string concatenation to prevent rewriting of
+ // ::google::protobuf.
+ ret = StringReplace(ret,
+ "::google::"
+ "protobuf",
+ "::PROTOBUF_NAMESPACE_ID", false);
+ }
+ return ret;
+}
+
+std::string Namespace(const Descriptor* d, const Options& options) {
+ return Namespace(d->file(), options);
+}
+
+std::string Namespace(const FieldDescriptor* d, const Options& options) {
+ return Namespace(d->file(), options);
+}
+
+std::string Namespace(const EnumDescriptor* d, const Options& options) {
+ return Namespace(d->file(), options);
+}
+
+std::string DefaultInstanceType(const Descriptor* descriptor,
+ const Options& options) {
+ return ClassName(descriptor) + "DefaultTypeInternal";
+}
+
+std::string DefaultInstanceName(const Descriptor* descriptor,
+ const Options& options) {
+ return "_" + ClassName(descriptor, false) + "_default_instance_";
+}
+
+std::string DefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options) {
+ return DefaultInstanceName(descriptor, options) + "ptr_";
+}
+
+std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
+ const Options& options) {
+ return QualifiedFileLevelSymbol(
+ descriptor->file(), DefaultInstanceName(descriptor, options), options);
+}
+
+std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options) {
+ return QualifiedDefaultInstanceName(descriptor, options) + "ptr_";
+}
+
+std::string DescriptorTableName(const FileDescriptor* file,
+ const Options& options) {
+ return UniqueName("descriptor_table", file, options);
+}
+
+std::string FileDllExport(const FileDescriptor* file, const Options& options) {
+ return UniqueName("PROTOBUF_INTERNAL_EXPORT", file, options);
+}
+
+std::string SuperClassName(const Descriptor* descriptor,
+ const Options& options) {
+ if (!HasDescriptorMethods(descriptor->file(), options)) {
+ return "::" + ProtobufNamespace(options) + "::MessageLite";
+ }
+ auto simple_base = SimpleBaseClass(descriptor, options);
+ if (simple_base.empty()) {
+ return "::" + ProtobufNamespace(options) + "::Message";
+ }
+ return "::" + ProtobufNamespace(options) + "::internal::" + simple_base;
+}
+
+std::string ResolveKeyword(const std::string& name) {
+ if (kKeywords.count(name) > 0) {
+ return name + "_";
+ }
+ return name;
+}
+
+std::string FieldName(const FieldDescriptor* field) {
+ std::string result = field->name();
+ LowerString(&result);
+ if (kKeywords.count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
+std::string OneofCaseConstantName(const FieldDescriptor* field) {
+ GOOGLE_DCHECK(field->containing_oneof());
+ std::string field_name = UnderscoresToCamelCase(field->name(), true);
+ return "k" + field_name;
+}
+
+std::string QualifiedOneofCaseConstantName(const FieldDescriptor* field) {
+ GOOGLE_DCHECK(field->containing_oneof());
+ const std::string qualification =
+ QualifiedClassName(field->containing_type());
+ return StrCat(qualification, "::", OneofCaseConstantName(field));
+}
+
+std::string EnumValueName(const EnumValueDescriptor* enum_value) {
+ std::string result = enum_value->name();
+ if (kKeywords.count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
+int EstimateAlignmentSize(const FieldDescriptor* field) {
+ if (field == nullptr) return 0;
+ if (field->is_repeated()) return 8;
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return 1;
+
+ case FieldDescriptor::CPPTYPE_INT32:
+ case FieldDescriptor::CPPTYPE_UINT32:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return 4;
+
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return 8;
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1; // Make compiler happy.
+}
+
+std::string FieldConstantName(const FieldDescriptor* field) {
+ std::string field_name = UnderscoresToCamelCase(field->name(), true);
+ std::string result = "k" + field_name + "FieldNumber";
+
+ if (!field->is_extension() &&
+ field->containing_type()->FindFieldByCamelcaseName(
+ field->camelcase_name()) != field) {
+ // This field's camelcase name is not unique. As a hack, add the field
+ // number to the constant name. This makes the constant rather useless,
+ // but what can we do?
+ result += "_" + StrCat(field->number());
+ }
+
+ return result;
+}
+
+std::string FieldMessageTypeName(const FieldDescriptor* field,
+ const Options& options) {
+ // Note: The Google-internal version of Protocol Buffers uses this function
+ // as a hook point for hacks to support legacy code.
+ return QualifiedClassName(field->message_type(), options);
+}
+
+std::string StripProto(const std::string& filename) {
+ /*
+ * TODO(github/georgthegreat) remove this proxy method
+ * once Google's internal codebase will become ready
+ */
+ return compiler::StripProto(filename);
+}
+
+const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
+ switch (type) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return "int32_t";
+ case FieldDescriptor::CPPTYPE_INT64:
+ return "int64_t";
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return "uint32_t";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return "uint64_t";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "double";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "float";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "bool";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return "int";
+ case FieldDescriptor::CPPTYPE_STRING:
+ return "std::string";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return nullptr;
+
+ // No default because we want the compiler to complain if any new
+ // CppTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return nullptr;
+}
+
+std::string PrimitiveTypeName(const Options& options,
+ FieldDescriptor::CppType type) {
+ switch (type) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return IntTypeName(options, "int32");
+ case FieldDescriptor::CPPTYPE_INT64:
+ return IntTypeName(options, "int64");
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return IntTypeName(options, "uint32");
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return IntTypeName(options, "uint64");
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "double";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "float";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "bool";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return "int";
+ case FieldDescriptor::CPPTYPE_STRING:
+ return "std::string";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "";
+
+ // No default because we want the compiler to complain if any new
+ // CppTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32:
+ return "Int32";
+ case FieldDescriptor::TYPE_INT64:
+ return "Int64";
+ case FieldDescriptor::TYPE_UINT32:
+ return "UInt32";
+ case FieldDescriptor::TYPE_UINT64:
+ return "UInt64";
+ case FieldDescriptor::TYPE_SINT32:
+ return "SInt32";
+ case FieldDescriptor::TYPE_SINT64:
+ return "SInt64";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "Fixed32";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "Fixed64";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "SFixed32";
+ 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_ENUM:
+ return "Enum";
+
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ 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 "";
+}
+
+std::string Int32ToString(int number) {
+ if (number == std::numeric_limits<int32_t>::min()) {
+ // This needs to be special-cased, see explanation here:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
+ return StrCat(number + 1, " - 1");
+ } else {
+ return StrCat(number);
+ }
+}
+
+static std::string Int64ToString(int64_t number) {
+ if (number == std::numeric_limits<int64_t>::min()) {
+ // This needs to be special-cased, see explanation here:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
+ return StrCat("int64_t{", number + 1, "} - 1");
+ }
+ return StrCat("int64_t{", number, "}");
+}
+
+static std::string UInt64ToString(uint64_t number) {
+ return StrCat("uint64_t{", number, "u}");
+}
+
+std::string DefaultValue(const FieldDescriptor* field) {
+ return DefaultValue(Options(), field);
+}
+
+std::string DefaultValue(const Options& options, const FieldDescriptor* field) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return Int32ToString(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return StrCat(field->default_value_uint32()) + "u";
+ case FieldDescriptor::CPPTYPE_INT64:
+ return Int64ToString(field->default_value_int64());
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return UInt64ToString(field->default_value_uint64());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == std::numeric_limits<double>::infinity()) {
+ return "std::numeric_limits<double>::infinity()";
+ } else if (value == -std::numeric_limits<double>::infinity()) {
+ return "-std::numeric_limits<double>::infinity()";
+ } else if (value != value) {
+ return "std::numeric_limits<double>::quiet_NaN()";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field->default_value_float();
+ if (value == std::numeric_limits<float>::infinity()) {
+ return "std::numeric_limits<float>::infinity()";
+ } else if (value == -std::numeric_limits<float>::infinity()) {
+ return "-std::numeric_limits<float>::infinity()";
+ } else if (value != value) {
+ return "std::numeric_limits<float>::quiet_NaN()";
+ } else {
+ std::string float_value = SimpleFtoa(value);
+ // If floating point value contains a period (.) or an exponent
+ // (either E or e), then append suffix 'f' to make it a float
+ // literal.
+ if (float_value.find_first_of(".eE") != std::string::npos) {
+ float_value.push_back('f');
+ }
+ return float_value;
+ }
+ }
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ // Lazy: Generate a static_cast because we don't have a helper function
+ // that constructs the full name of an enum value.
+ return strings::Substitute(
+ "static_cast< $0 >($1)", ClassName(field->enum_type(), true),
+ Int32ToString(field->default_value_enum()->number()));
+ case FieldDescriptor::CPPTYPE_STRING:
+ return "\"" +
+ EscapeTrigraphs(CEscape(field->default_value_string())) +
+ "\"";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "*" + FieldMessageTypeName(field, options) +
+ "::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
+ // new type is added.)
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+// Convert a file name into a valid identifier.
+std::string FilenameIdentifier(const std::string& filename) {
+ std::string result;
+ for (int i = 0; i < filename.size(); i++) {
+ if (ascii_isalnum(filename[i])) {
+ result.push_back(filename[i]);
+ } else {
+ // Not alphanumeric. To avoid any possibility of name conflicts we
+ // use the hex code for the character.
+ StrAppend(&result, "_",
+ strings::Hex(static_cast<uint8_t>(filename[i])));
+ }
+ }
+ return result;
+}
+
+std::string UniqueName(const std::string& name, const std::string& filename,
+ const Options& options) {
+ return name + "_" + FilenameIdentifier(filename);
+}
+
+// Return the qualified C++ name for a file level symbol.
+std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
+ const std::string& name,
+ const Options& options) {
+ if (file->package().empty()) {
+ return StrCat("::", name);
+ }
+ return StrCat(Namespace(file, options), "::", name);
+}
+
+// Escape C++ trigraphs by escaping question marks to \?
+std::string EscapeTrigraphs(const std::string& to_escape) {
+ return StringReplace(to_escape, "?", "\\?", true);
+}
+
+// Escaped function name to eliminate naming conflict.
+std::string SafeFunctionName(const Descriptor* descriptor,
+ const FieldDescriptor* field,
+ const std::string& prefix) {
+ // Do not use FieldName() since it will escape keywords.
+ std::string name = field->name();
+ LowerString(&name);
+ std::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 IsStringInlined(const FieldDescriptor* descriptor,
+ const Options& options) {
+ (void)descriptor;
+ (void)options;
+ return false;
+}
+
+static bool HasLazyFields(const Descriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
+ if (IsLazy(descriptor->field(field_idx), options, scc_analyzer)) {
+ return true;
+ }
+ }
+ for (int idx = 0; idx < descriptor->extension_count(); idx++) {
+ if (IsLazy(descriptor->extension(idx), options, scc_analyzer)) {
+ return true;
+ }
+ }
+ for (int idx = 0; idx < descriptor->nested_type_count(); idx++) {
+ if (HasLazyFields(descriptor->nested_type(idx), options, scc_analyzer)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Does the given FileDescriptor use lazy fields?
+bool HasLazyFields(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ const Descriptor* descriptor(file->message_type(i));
+ if (HasLazyFields(descriptor, options, scc_analyzer)) {
+ return true;
+ }
+ }
+ for (int field_idx = 0; field_idx < file->extension_count(); field_idx++) {
+ if (IsLazy(file->extension(field_idx), options, scc_analyzer)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool HasRepeatedFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) {
+ return true;
+ }
+ }
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ if (HasRepeatedFields(descriptor->nested_type(i))) return true;
+ }
+ return false;
+}
+
+bool HasRepeatedFields(const FileDescriptor* file) {
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasRepeatedFields(file->message_type(i))) return true;
+ }
+ return false;
+}
+
+static bool IsStringPieceField(const FieldDescriptor* field,
+ const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
+}
+
+static bool HasStringPieceFields(const Descriptor* descriptor,
+ const Options& options) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ if (IsStringPieceField(descriptor->field(i), options)) return true;
+ }
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ if (HasStringPieceFields(descriptor->nested_type(i), options)) return true;
+ }
+ return false;
+}
+
+bool HasStringPieceFields(const FileDescriptor* file, const Options& options) {
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasStringPieceFields(file->message_type(i), options)) return true;
+ }
+ return false;
+}
+
+static bool IsCordField(const FieldDescriptor* field, const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::CORD;
+}
+
+static bool HasCordFields(const Descriptor* descriptor,
+ const Options& options) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ if (IsCordField(descriptor->field(i), options)) return true;
+ }
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ if (HasCordFields(descriptor->nested_type(i), options)) return true;
+ }
+ return false;
+}
+
+bool HasCordFields(const FileDescriptor* file, const Options& options) {
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasCordFields(file->message_type(i), options)) return true;
+ }
+ return false;
+}
+
+static bool HasExtensionsOrExtendableMessage(const Descriptor* descriptor) {
+ if (descriptor->extension_range_count() > 0) return true;
+ if (descriptor->extension_count() > 0) return true;
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ if (HasExtensionsOrExtendableMessage(descriptor->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool HasExtensionsOrExtendableMessage(const FileDescriptor* file) {
+ if (file->extension_count() > 0) return true;
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasExtensionsOrExtendableMessage(file->message_type(i))) return true;
+ }
+ return false;
+}
+
+static bool HasMapFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ if (descriptor->field(i)->is_map()) {
+ return true;
+ }
+ }
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ if (HasMapFields(descriptor->nested_type(i))) return true;
+ }
+ return false;
+}
+
+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) {
+ if (HasEnumDefinitions(message_type->nested_type(i))) return true;
+ }
+ return false;
+}
+
+bool HasEnumDefinitions(const FileDescriptor* file) {
+ if (file->enum_type_count() > 0) return true;
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasEnumDefinitions(file->message_type(i))) return true;
+ }
+ return false;
+}
+
+bool ShouldVerify(const Descriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ (void)descriptor;
+ (void)options;
+ (void)scc_analyzer;
+ return false;
+}
+
+bool ShouldVerify(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ (void)file;
+ (void)options;
+ (void)scc_analyzer;
+ 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,
+ const Options& options) {
+ GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+ if (options.opensource_runtime) {
+ // Open-source protobuf release only supports STRING ctype.
+ return FieldOptions::STRING;
+ } else {
+ // Google-internal supports all ctypes.
+ return field->options().ctype();
+ }
+}
+
+bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options) {
+ return descriptor->name() == kAnyProtoFile;
+}
+
+bool IsAnyMessage(const Descriptor* descriptor, const Options& options) {
+ return descriptor->name() == kAnyMessageName &&
+ IsAnyMessage(descriptor->file(), options);
+}
+
+bool IsWellKnownMessage(const FileDescriptor* file) {
+ static const std::unordered_set<std::string> well_known_files{
+ "google/protobuf/any.proto",
+ "google/protobuf/api.proto",
+ "google/protobuf/compiler/plugin.proto",
+ "google/protobuf/descriptor.proto",
+ "google/protobuf/duration.proto",
+ "google/protobuf/empty.proto",
+ "google/protobuf/field_mask.proto",
+ "google/protobuf/source_context.proto",
+ "google/protobuf/struct.proto",
+ "google/protobuf/timestamp.proto",
+ "google/protobuf/type.proto",
+ "google/protobuf/wrappers.proto",
+ };
+ return well_known_files.find(file->name()) != well_known_files.end();
+}
+
+static bool FieldEnforceUtf8(const FieldDescriptor* field,
+ const Options& options) {
+ return true;
+}
+
+static bool FileUtf8Verification(const FileDescriptor* file,
+ const Options& options) {
+ return true;
+}
+
+// Which level of UTF-8 enforcemant is placed on this file.
+Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+ const Options& options) {
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ FieldEnforceUtf8(field, options)) {
+ return Utf8CheckMode::kStrict;
+ } else if (GetOptimizeFor(field->file(), options) !=
+ FileOptions::LITE_RUNTIME &&
+ FileUtf8Verification(field->file(), options)) {
+ return Utf8CheckMode::kVerify;
+ } else {
+ return Utf8CheckMode::kNone;
+ }
+}
+
+static void GenerateUtf8CheckCode(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const char* strict_function,
+ const char* verify_function,
+ const Formatter& format) {
+ switch (GetUtf8CheckMode(field, options)) {
+ case Utf8CheckMode::kStrict: {
+ if (for_parse) {
+ format("DO_(");
+ }
+ format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function);
+ format.Indent();
+ format(parameters);
+ if (for_parse) {
+ format("::$proto_ns$::internal::WireFormatLite::PARSE,\n");
+ } else {
+ format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n");
+ }
+ format("\"$1$\")", field->full_name());
+ if (for_parse) {
+ format(")");
+ }
+ format(";\n");
+ format.Outdent();
+ break;
+ }
+ case Utf8CheckMode::kVerify: {
+ format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function);
+ format.Indent();
+ format(parameters);
+ if (for_parse) {
+ format("::$proto_ns$::internal::WireFormat::PARSE,\n");
+ } else {
+ format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n");
+ }
+ format("\"$1$\");\n", field->full_name());
+ format.Outdent();
+ break;
+ }
+ case Utf8CheckMode::kNone:
+ break;
+ }
+}
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format) {
+ GenerateUtf8CheckCode(field, options, for_parse, parameters,
+ "VerifyUtf8String", "VerifyUTF8StringNamedField",
+ format);
+}
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format) {
+ GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord",
+ "VerifyUTF8CordNamedField", format);
+}
+
+void FlattenMessagesInFile(const FileDescriptor* file,
+ std::vector<const Descriptor*>* result) {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ ForEachMessage(file->message_type(i), [&](const Descriptor* descriptor) {
+ result->push_back(descriptor);
+ });
+ }
+}
+
+bool HasWeakFields(const Descriptor* descriptor, const Options& options) {
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (IsWeak(descriptor->field(i), options)) return true;
+ }
+ return false;
+}
+
+bool HasWeakFields(const FileDescriptor* file, const Options& options) {
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasWeakFields(file->message_type(i), options)) return true;
+ }
+ return false;
+}
+
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+ const Options& options) {
+ return options.lite_implicit_weak_fields &&
+ GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
+}
+
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return UsingImplicitWeakFields(field->file(), options) &&
+ field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ !field->is_required() && !field->is_map() && !field->is_extension() &&
+ !field->real_containing_oneof() &&
+ !IsWellKnownMessage(field->message_type()->file()) &&
+ field->message_type()->file()->name() !=
+ "net/proto2/proto/descriptor.proto" &&
+ // We do not support implicit weak fields between messages in the same
+ // strongly-connected component.
+ scc_analyzer->GetSCC(field->containing_type()) !=
+ scc_analyzer->GetSCC(field->message_type());
+}
+
+MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
+ if (analysis_cache_.count(scc)) return analysis_cache_[scc];
+ MessageAnalysis result;
+ if (UsingImplicitWeakFields(scc->GetFile(), options_)) {
+ result.contains_weak = true;
+ }
+ for (int i = 0; i < scc->descriptors.size(); i++) {
+ const Descriptor* descriptor = scc->descriptors[i];
+ if (descriptor->extension_range_count() > 0) {
+ result.contains_extension = true;
+ }
+ for (int j = 0; j < descriptor->field_count(); j++) {
+ const FieldDescriptor* field = descriptor->field(j);
+ if (field->is_required()) {
+ result.contains_required = true;
+ }
+ if (field->options().weak()) {
+ result.contains_weak = true;
+ }
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES: {
+ if (field->options().ctype() == FieldOptions::CORD) {
+ result.contains_cord = true;
+ }
+ break;
+ }
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE: {
+ const SCC* child = analyzer_.GetSCC(field->message_type());
+ if (child != scc) {
+ MessageAnalysis analysis = GetSCCAnalysis(child);
+ result.contains_cord |= analysis.contains_cord;
+ result.contains_extension |= analysis.contains_extension;
+ if (!ShouldIgnoreRequiredFieldCheck(field, options_)) {
+ result.contains_required |= analysis.contains_required;
+ }
+ result.contains_weak |= analysis.contains_weak;
+ } else {
+ // This field points back into the same SCC hence the messages
+ // in the SCC are recursive. Note if SCC contains more than two
+ // nodes it has to be recursive, however this test also works for
+ // a single node that is recursive.
+ result.is_recursive = true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ // We deliberately only insert the result here. After we contracted the SCC
+ // in the graph, the graph should be a DAG. Hence we shouldn't need to mark
+ // nodes visited as we can never return to them. By inserting them here
+ // we will go in an infinite loop if the SCC is not correct.
+ return analysis_cache_[scc] = result;
+}
+
+void ListAllFields(const Descriptor* d,
+ std::vector<const FieldDescriptor*>* fields) {
+ // Collect sub messages
+ for (int i = 0; i < d->nested_type_count(); i++) {
+ ListAllFields(d->nested_type(i), fields);
+ }
+ // Collect message level extensions.
+ for (int i = 0; i < d->extension_count(); i++) {
+ fields->push_back(d->extension(i));
+ }
+ // Add types of fields necessary
+ for (int i = 0; i < d->field_count(); i++) {
+ fields->push_back(d->field(i));
+ }
+}
+
+void ListAllFields(const FileDescriptor* d,
+ std::vector<const FieldDescriptor*>* fields) {
+ // Collect file level message.
+ for (int i = 0; i < d->message_type_count(); i++) {
+ ListAllFields(d->message_type(i), fields);
+ }
+ // Collect message level extensions.
+ for (int i = 0; i < d->extension_count(); i++) {
+ fields->push_back(d->extension(i));
+ }
+}
+
+void ListAllTypesForServices(const FileDescriptor* fd,
+ std::vector<const Descriptor*>* types) {
+ for (int i = 0; i < fd->service_count(); i++) {
+ const ServiceDescriptor* sd = fd->service(i);
+ for (int j = 0; j < sd->method_count(); j++) {
+ const MethodDescriptor* method = sd->method(j);
+ types->push_back(method->input_type());
+ types->push_back(method->output_type());
+ }
+ }
+}
+
+bool GetBootstrapBasename(const Options& options, const std::string& basename,
+ std::string* bootstrap_basename) {
+ if (options.opensource_runtime) {
+ return false;
+ }
+
+ std::unordered_map<std::string, std::string> bootstrap_mapping{
+ {"net/proto2/proto/descriptor",
+ "net/proto2/internal/descriptor"},
+ {"net/proto2/compiler/proto/plugin",
+ "net/proto2/compiler/proto/plugin"},
+ {"net/proto2/compiler/proto/profile",
+ "net/proto2/compiler/proto/profile_bootstrap"},
+ };
+ auto iter = bootstrap_mapping.find(basename);
+ if (iter == bootstrap_mapping.end()) {
+ *bootstrap_basename = basename;
+ return false;
+ } else {
+ *bootstrap_basename = iter->second;
+ return true;
+ }
+}
+
+bool IsBootstrapProto(const Options& options, const FileDescriptor* file) {
+ std::string my_name = StripProto(file->name());
+ return GetBootstrapBasename(options, my_name, &my_name);
+}
+
+bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
+ bool bootstrap_flag, std::string* basename) {
+ std::string bootstrap_basename;
+ if (!GetBootstrapBasename(options, *basename, &bootstrap_basename)) {
+ return false;
+ }
+
+ if (bootstrap_flag) {
+ // Adjust basename, but don't abort code generation.
+ *basename = bootstrap_basename;
+ return false;
+ } else {
+ std::string forward_to_basename = bootstrap_basename;
+
+ // Generate forwarding headers and empty .pb.cc.
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(*basename + ".pb.h"));
+ io::Printer printer(output.get(), '$', nullptr);
+ printer.Print(
+ "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
+ "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
+ "#include \"$forward_to_basename$.pb.h\" // IWYU pragma: export\n"
+ "#endif // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n",
+ "forward_to_basename", forward_to_basename, "filename_identifier",
+ FilenameIdentifier(*basename));
+
+ if (!options.opensource_runtime) {
+ // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG
+ // protocoltype is SWIG'ed and we need to forward
+ if (*basename == "net/proto/protocoltype") {
+ printer.Print(
+ "#ifdef SWIG\n"
+ "%include \"$forward_to_basename$.pb.h\"\n"
+ "#endif // SWIG\n",
+ "forward_to_basename", forward_to_basename);
+ }
+ }
+ }
+
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(*basename + ".proto.h"));
+ io::Printer printer(output.get(), '$', nullptr);
+ printer.Print(
+ "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
+ "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
+ "#include \"$forward_to_basename$.proto.h\" // IWYU pragma: "
+ "export\n"
+ "#endif // "
+ "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n",
+ "forward_to_basename", forward_to_basename, "filename_identifier",
+ FilenameIdentifier(*basename));
+ }
+
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(*basename + ".pb.cc"));
+ io::Printer printer(output.get(), '$', nullptr);
+ printer.Print("\n");
+ }
+
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(*basename + ".pb.h.meta"));
+ }
+
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(*basename + ".proto.h.meta"));
+ }
+
+ // Abort code generation.
+ return true;
+ }
+}
+
+static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file,
+ const Options& options,
+ bool* has_opt_codesize_extension) {
+ std::vector<const FieldDescriptor*> fields;
+ auto reflection = msg.GetReflection();
+ reflection->ListFields(msg, &fields);
+ for (auto field : fields) {
+ const auto* field_msg = field->message_type();
+ if (field_msg == nullptr) {
+ // It so happens that enums Is_Valid are still generated so enums work.
+ // Only messages have potential problems.
+ continue;
+ }
+ // If this option has an extension set AND that extension is defined in the
+ // same file we have bootstrap problem.
+ if (field->is_extension()) {
+ const auto* msg_extension_file = field->message_type()->file();
+ if (msg_extension_file == file) return true;
+ if (has_opt_codesize_extension &&
+ GetOptimizeFor(msg_extension_file, options) ==
+ FileOptions::CODE_SIZE) {
+ *has_opt_codesize_extension = true;
+ }
+ }
+ // Recurse in this field to see if there is a problem in there
+ if (field->is_repeated()) {
+ for (int i = 0; i < reflection->FieldSize(msg, field); i++) {
+ if (HasExtensionFromFile(reflection->GetRepeatedMessage(msg, field, i),
+ file, options, has_opt_codesize_extension)) {
+ return true;
+ }
+ }
+ } else {
+ if (HasExtensionFromFile(reflection->GetMessage(msg, field), file,
+ options, has_opt_codesize_extension)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool HasBootstrapProblem(const FileDescriptor* file,
+ const Options& options,
+ bool* has_opt_codesize_extension) {
+ static auto& cache = *new std::unordered_map<const FileDescriptor*, bool>;
+ auto it = cache.find(file);
+ if (it != cache.end()) return it->second;
+ // In order to build the data structures for the reflective parse, it needs
+ // to parse the serialized descriptor describing all the messages defined in
+ // this file. Obviously this presents a bootstrap problem for descriptor
+ // messages.
+ if (file->name() == "net/proto2/proto/descriptor.proto" ||
+ file->name() == "google/protobuf/descriptor.proto") {
+ return true;
+ }
+ // Unfortunately we're not done yet. The descriptor option messages allow
+ // for extensions. So we need to be able to parse these extensions in order
+ // to parse the file descriptor for a file that has custom options. This is a
+ // problem when these custom options extensions are defined in the same file.
+ FileDescriptorProto linkedin_fd_proto;
+ const DescriptorPool* pool = file->pool();
+ const Descriptor* fd_proto_descriptor =
+ pool->FindMessageTypeByName(linkedin_fd_proto.GetTypeName());
+ // Not all pools have descriptor.proto in them. In these cases there for sure
+ // are no custom options.
+ if (fd_proto_descriptor == nullptr) return false;
+
+ // It's easier to inspect file as a proto, because we can use reflection on
+ // the proto to iterate over all content.
+ file->CopyTo(&linkedin_fd_proto);
+
+ // linkedin_fd_proto is a generated proto linked in the proto compiler. As
+ // such it doesn't know the extensions that are potentially present in the
+ // descriptor pool constructed from the protos that are being compiled. These
+ // custom options are therefore in the unknown fields.
+ // By building the corresponding FileDescriptorProto in the pool constructed
+ // by the protos that are being compiled, ie. file's pool, the unknown fields
+ // are converted to extensions.
+ DynamicMessageFactory factory(pool);
+ Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New();
+ fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString());
+
+ bool& res = cache[file];
+ res = HasExtensionFromFile(*fd_proto, file, options,
+ has_opt_codesize_extension);
+ delete fd_proto;
+ return res;
+}
+
+FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options,
+ bool* has_opt_codesize_extension) {
+ if (has_opt_codesize_extension) *has_opt_codesize_extension = false;
+ switch (options.enforce_mode) {
+ case EnforceOptimizeMode::kSpeed:
+ return FileOptions::SPEED;
+ case EnforceOptimizeMode::kLiteRuntime:
+ return FileOptions::LITE_RUNTIME;
+ case EnforceOptimizeMode::kCodeSize:
+ if (file->options().optimize_for() == FileOptions::LITE_RUNTIME) {
+ return FileOptions::LITE_RUNTIME;
+ }
+ if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) {
+ return FileOptions::SPEED;
+ }
+ return FileOptions::CODE_SIZE;
+ case EnforceOptimizeMode::kNoEnforcement:
+ if (file->options().optimize_for() == FileOptions::CODE_SIZE) {
+ if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) {
+ GOOGLE_LOG(WARNING) << "Proto states optimize_for = CODE_SIZE, but we "
+ "cannot honor that because it contains custom option "
+ "extensions defined in the same proto.";
+ return FileOptions::SPEED;
+ }
+ }
+ return file->options().optimize_for();
+ }
+
+ GOOGLE_LOG(FATAL) << "Unknown optimization enforcement requested.";
+ // The phony return below serves to silence a warning from GCC 8.
+ return FileOptions::SPEED;
+}
+
+bool EnableMessageOwnedArena(const Descriptor* desc) {
+ (void)desc;
+ return false;
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.h
new file mode 100644
index 00000000..dd380c7e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_helpers.h
@@ -0,0 +1,971 @@
+// 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 <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <string>
+
+#include <compiler/cpp/cpp_options.h>
+#include <compiler/cpp/cpp_names.h>
+#include <compiler/scc.h>
+#include <compiler/code_generator.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <descriptor.h>
+#include <port.h>
+#include <stubs/strutil.h>
+
+// Must be included last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+inline std::string ProtobufNamespace(const Options& /* options */) {
+ return "PROTOBUF_NAMESPACE_ID";
+}
+
+inline std::string MacroPrefix(const Options& /* options */) {
+ return "GOOGLE_PROTOBUF";
+}
+
+inline std::string DeprecatedAttribute(const Options& /* options */,
+ const FieldDescriptor* d) {
+ return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : "";
+}
+
+inline std::string DeprecatedAttribute(const Options& /* options */,
+ const EnumValueDescriptor* d) {
+ return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : "";
+}
+
+// Commonly-used separator comments. Thick is a line of '=', thin is a line
+// of '-'.
+extern const char kThickSeparator[];
+extern const char kThinSeparator[];
+
+void SetCommonVars(const Options& options,
+ std::map<std::string, std::string>* variables);
+
+void SetUnknownFieldsVariable(const Descriptor* descriptor,
+ const Options& options,
+ std::map<std::string, std::string>* variables);
+
+bool GetBootstrapBasename(const Options& options, const std::string& basename,
+ std::string* bootstrap_basename);
+bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context,
+ bool bootstrap_flag, std::string* basename);
+bool IsBootstrapProto(const Options& options, const FileDescriptor* file);
+
+// Name space of the proto file. This namespace is such that the string
+// "<namespace>::some_name" is the correct fully qualified namespace.
+// This means if the package is empty the namespace is "", and otherwise
+// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
+std::string Namespace(const FileDescriptor* d, const Options& options);
+std::string Namespace(const Descriptor* d, const Options& options);
+std::string Namespace(const FieldDescriptor* d, const Options& options);
+std::string Namespace(const EnumDescriptor* d, const Options& options);
+
+// Returns true if it's safe to reset "field" to zero.
+bool CanInitializeByZeroing(const FieldDescriptor* field);
+
+std::string ClassName(const Descriptor* descriptor);
+std::string ClassName(const EnumDescriptor* enum_descriptor);
+
+std::string QualifiedClassName(const Descriptor* d, const Options& options);
+std::string QualifiedClassName(const EnumDescriptor* d, const Options& options);
+
+std::string QualifiedClassName(const Descriptor* d);
+std::string QualifiedClassName(const EnumDescriptor* d);
+
+// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
+// unreadable at the callsite.
+// 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
+inline std::string ClassName(const Descriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor, Options())
+ : ClassName(descriptor);
+}
+
+inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) {
+ return qualified ? QualifiedClassName(descriptor, Options())
+ : ClassName(descriptor);
+}
+
+// Returns the extension name prefixed with the class name if nested but without
+// the package name.
+std::string ExtensionName(const FieldDescriptor* d);
+
+std::string QualifiedExtensionName(const FieldDescriptor* d,
+ const Options& options);
+std::string QualifiedExtensionName(const FieldDescriptor* d);
+
+// Type name of default instance.
+std::string DefaultInstanceType(const Descriptor* descriptor,
+ const Options& options);
+
+// Non-qualified name of the default_instance of this message.
+std::string DefaultInstanceName(const Descriptor* descriptor,
+ const Options& options);
+
+// Non-qualified name of the default instance pointer. This is used only for
+// implicit weak fields, where we need an extra indirection.
+std::string DefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options);
+
+// Fully qualified name of the default_instance of this message.
+std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
+ const Options& options);
+
+// Fully qualified name of the default instance pointer.
+std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
+ const Options& options);
+
+// DescriptorTable variable name.
+std::string DescriptorTableName(const FileDescriptor* file,
+ const Options& options);
+
+// When declaring symbol externs from another file, this macro will supply the
+// dllexport needed for the target file, if any.
+std::string FileDllExport(const FileDescriptor* file, const Options& options);
+
+// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
+std::string SuperClassName(const Descriptor* descriptor,
+ const Options& options);
+
+// Adds an underscore if necessary to prevent conflicting with a keyword.
+std::string ResolveKeyword(const std::string& name);
+
+// 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().
+std::string FieldName(const FieldDescriptor* field);
+
+// Returns an estimate of the compiler's alignment for the field. This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules. The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field);
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+std::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);
+std::string FieldMessageTypeName(const FieldDescriptor* field,
+ const Options& options);
+
+// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
+const char* PrimitiveTypeName(FieldDescriptor::CppType type);
+std::string PrimitiveTypeName(const Options& options,
+ 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.
+std::string Int32ToString(int number);
+
+// Get code that evaluates to the field's default value.
+std::string DefaultValue(const Options& options, const FieldDescriptor* field);
+
+// Compatibility function for callers outside proto2.
+std::string DefaultValue(const FieldDescriptor* field);
+
+// Convert a file name into a valid identifier.
+std::string FilenameIdentifier(const std::string& filename);
+
+// For each .proto file generates a unique name. To prevent collisions of
+// symbols in the global namespace
+std::string UniqueName(const std::string& name, const std::string& filename,
+ const Options& options);
+inline std::string UniqueName(const std::string& name, const FileDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->name(), options);
+}
+inline std::string UniqueName(const std::string& name, const Descriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+inline std::string UniqueName(const std::string& name, const EnumDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+inline std::string UniqueName(const std::string& name,
+ const ServiceDescriptor* d,
+ const Options& options) {
+ return UniqueName(name, d->file(), options);
+}
+
+// Versions for call sites that only support the internal runtime (like proto1
+// support).
+inline Options InternalRuntimeOptions() {
+ Options options;
+ options.opensource_runtime = false;
+ return options;
+}
+inline std::string UniqueName(const std::string& name,
+ const std::string& filename) {
+ return UniqueName(name, filename, InternalRuntimeOptions());
+}
+inline std::string UniqueName(const std::string& name,
+ const FileDescriptor* d) {
+ return UniqueName(name, d->name(), InternalRuntimeOptions());
+}
+inline std::string UniqueName(const std::string& name, const Descriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+inline std::string UniqueName(const std::string& name,
+ const EnumDescriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+inline std::string UniqueName(const std::string& name,
+ const ServiceDescriptor* d) {
+ return UniqueName(name, d->file(), InternalRuntimeOptions());
+}
+
+// Return the qualified C++ name for a file level symbol.
+std::string QualifiedFileLevelSymbol(const FileDescriptor* file,
+ const std::string& name,
+ const Options& options);
+
+// Escape C++ trigraphs by escaping question marks to \?
+std::string EscapeTrigraphs(const std::string& to_escape);
+
+// Escaped function name to eliminate naming conflict.
+std::string SafeFunctionName(const Descriptor* descriptor,
+ const FieldDescriptor* field,
+ const std::string& prefix);
+
+// Returns true if generated messages have public unknown fields accessors
+inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
+ return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
+FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options);
+
+// Determines whether unknown fields will be stored in an UnknownFieldSet or
+// a string.
+inline bool UseUnknownFieldSet(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
+}
+
+inline bool IsWeak(const FieldDescriptor* field, const Options& options) {
+ if (field->options().weak()) {
+ GOOGLE_CHECK(!options.opensource_runtime);
+ return true;
+ }
+ return false;
+}
+
+bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
+
+// 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,
+ const Options& options);
+
+inline bool IsCord(const FieldDescriptor* field, const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::CORD;
+}
+
+inline bool IsString(const FieldDescriptor* field, const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::STRING;
+}
+
+inline bool IsStringPiece(const FieldDescriptor* field,
+ const Options& options) {
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
+}
+
+class MessageSCCAnalyzer;
+
+// Does the given FileDescriptor use lazy fields?
+bool HasLazyFields(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+// Is the given field a supported lazy field?
+bool IsLazy(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+inline bool IsLazilyVerifiedLazy(const FieldDescriptor* field,
+ const Options& options) {
+ return field->options().lazy() && !field->is_repeated() &&
+ field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME &&
+ !options.opensource_runtime;
+}
+
+inline bool IsEagerlyVerifiedLazy(const FieldDescriptor* field,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ return IsLazy(field, options, scc_analyzer) && !field->options().lazy();
+}
+
+inline bool IsFieldUsed(const FieldDescriptor* /* field */,
+ const Options& /* options */) {
+ return true;
+}
+
+// Returns true if "field" is stripped.
+inline bool IsFieldStripped(const FieldDescriptor* /*field*/,
+ const Options& /*options*/) {
+ return false;
+}
+
+// Does the file contain any definitions that need extension_set.h?
+bool HasExtensionsOrExtendableMessage(const FileDescriptor* file);
+
+// Does the file have any repeated fields, necessitating the file to include
+// repeated_field.h? This does not include repeated extensions, since those are
+// all stored internally in an ExtensionSet, not a separate RepeatedField*.
+bool HasRepeatedFields(const FileDescriptor* file);
+
+// Does the file have any string/bytes fields with ctype=STRING_PIECE? This
+// does not include extensions, since ctype is ignored for extensions.
+bool HasStringPieceFields(const FileDescriptor* file, const Options& options);
+
+// Does the file have any string/bytes fields with ctype=CORD? This does not
+// include extensions, since ctype is ignored for extensions.
+bool HasCordFields(const FileDescriptor* file, const Options& options);
+
+// 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();
+}
+
+inline bool IsProto2MessageSet(const Descriptor* descriptor,
+ const Options& options) {
+ return !options.opensource_runtime &&
+ options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
+ !options.lite_implicit_weak_fields &&
+ descriptor->options().message_set_wire_format() &&
+ descriptor->full_name() == "google.protobuf.bridge.MessageSet";
+}
+
+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);
+
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter);
+
+inline bool IsProto3(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool HasHasbit(const FieldDescriptor* field) {
+ // This predicate includes proto3 message fields only if they have "optional".
+ // Foo submsg1 = 1; // HasHasbit() == false
+ // optional Foo submsg2 = 2; // HasHasbit() == true
+ // This is slightly odd, as adding "optional" to a singular proto3 field does
+ // not change the semantics or API. However whenever any field in a message
+ // has a hasbit, it forces reflection to include hasbit offsets for *all*
+ // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
+ // causing a sudden size regression for ~all proto3 messages, we give proto3
+ // message fields a hasbit only if "optional" is present. If the user is
+ // explicitly writing "optional", it is likely they are writing it on
+ // primitive fields also.
+ return (field->has_optional_keyword() || field->is_required()) &&
+ !field->options().weak();
+}
+
+// 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 FieldDescriptor* field) {
+ return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsCrossFileMessage(const FieldDescriptor* field) {
+ return field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ field->message_type()->file() != field->file();
+}
+
+inline std::string MakeDefaultName(const FieldDescriptor* field) {
+ return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
+ "_";
+}
+
+bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options);
+bool IsAnyMessage(const Descriptor* descriptor, const Options& options);
+
+bool IsWellKnownMessage(const FileDescriptor* descriptor);
+
+inline std::string IncludeGuard(const FileDescriptor* file, bool pb_h,
+ const Options& options) {
+ // If we are generating a .pb.h file and the proto_h option is enabled, then
+ // the .pb.h gets an extra suffix.
+ std::string filename_identifier = FilenameIdentifier(
+ file->name() + (pb_h && options.proto_h ? ".pb.h" : ""));
+
+ if (IsWellKnownMessage(file)) {
+ // For well-known messages we need third_party/protobuf and net/proto2 to
+ // have distinct include guards, because some source files include both and
+ // both need to be defined (the third_party copies will be in the
+ // google::protobuf_opensource namespace).
+ return MacroPrefix(options) + "_INCLUDED_" + filename_identifier;
+ } else {
+ // Ideally this case would use distinct include guards for opensource and
+ // google3 protos also. (The behavior of "first #included wins" is not
+ // ideal). But unfortunately some legacy code includes both and depends on
+ // the identical include guards to avoid compile errors.
+ //
+ // We should clean this up so that this case can be removed.
+ return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier;
+ }
+}
+
+// Returns the OptimizeMode for this file, furthermore it updates a status
+// bool if has_opt_codesize_extension is non-null. If this status bool is true
+// it means this file contains an extension that itself is defined as
+// optimized_for = CODE_SIZE.
+FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options,
+ bool* has_opt_codesize_extension);
+inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options, nullptr);
+}
+inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file,
+ const Options& options) {
+ bool has_opt_codesize_extension;
+ if (GetOptimizeFor(file, options, &has_opt_codesize_extension) ==
+ FileOptions::CODE_SIZE &&
+ has_opt_codesize_extension) {
+ // If this filedescriptor contains an extension from another file which
+ // is optimized_for = CODE_SIZE. We need to be careful in the ordering so
+ // we eagerly build the descriptors in the dependencies before building
+ // the descriptors of this file.
+ return true;
+ } else {
+ // If we have a generated code based parser we never need eager
+ // initialization of descriptors of our deps.
+ return false;
+ }
+}
+
+// This orders the messages in a .pb.cc as it's outputted by file.cc
+void FlattenMessagesInFile(const FileDescriptor* file,
+ std::vector<const Descriptor*>* result);
+inline std::vector<const Descriptor*> FlattenMessagesInFile(
+ const FileDescriptor* file) {
+ std::vector<const Descriptor*> result;
+ FlattenMessagesInFile(file, &result);
+ return result;
+}
+
+template <typename F>
+void ForEachMessage(const Descriptor* descriptor, F&& func) {
+ for (int i = 0; i < descriptor->nested_type_count(); i++)
+ ForEachMessage(descriptor->nested_type(i), std::forward<F&&>(func));
+ func(descriptor);
+}
+
+template <typename F>
+void ForEachMessage(const FileDescriptor* descriptor, F&& func) {
+ for (int i = 0; i < descriptor->message_type_count(); i++)
+ ForEachMessage(descriptor->message_type(i), std::forward<F&&>(func));
+}
+
+bool HasWeakFields(const Descriptor* desc, const Options& options);
+bool HasWeakFields(const FileDescriptor* desc, const Options& options);
+
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
+ const Options& options) {
+ // Do not check "required" for lazily verified lazy fields.
+ return IsLazilyVerifiedLazy(field, options);
+}
+
+struct MessageAnalysis {
+ bool is_recursive = false;
+ bool contains_cord = false;
+ bool contains_extension = false;
+ bool contains_required = false;
+ bool contains_weak = false; // Implicit weak as well.
+};
+
+// This class is used in FileGenerator, to ensure linear instead of
+// quadratic performance, if we do this per message we would get O(V*(V+E)).
+// Logically this is just only used in message.cc, but in the header for
+// FileGenerator to help share it.
+class PROTOC_EXPORT MessageSCCAnalyzer {
+ public:
+ explicit MessageSCCAnalyzer(const Options& options) : options_(options) {}
+
+ MessageAnalysis GetSCCAnalysis(const SCC* scc);
+
+ bool HasRequiredFields(const Descriptor* descriptor) {
+ MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+ return result.contains_required || result.contains_extension;
+ }
+ bool HasWeakField(const Descriptor* descriptor) {
+ MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+ return result.contains_weak;
+ }
+ const SCC* GetSCC(const Descriptor* descriptor) {
+ return analyzer_.GetSCC(descriptor);
+ }
+
+ private:
+ struct DepsGenerator {
+ std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
+ std::vector<const Descriptor*> deps;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->message_type()) {
+ deps.push_back(desc->field(i)->message_type());
+ }
+ }
+ return deps;
+ }
+ };
+ SCCAnalyzer<DepsGenerator> analyzer_;
+ Options options_;
+ std::map<const SCC*, MessageAnalysis> analysis_cache_;
+};
+
+void ListAllFields(const Descriptor* d,
+ std::vector<const FieldDescriptor*>* fields);
+void ListAllFields(const FileDescriptor* d,
+ std::vector<const FieldDescriptor*>* fields);
+
+template <class T>
+void ForEachField(const Descriptor* d, T&& func) {
+ for (int i = 0; i < d->nested_type_count(); i++) {
+ ForEachField(d->nested_type(i), std::forward<T&&>(func));
+ }
+ for (int i = 0; i < d->extension_count(); i++) {
+ func(d->extension(i));
+ }
+ for (int i = 0; i < d->field_count(); i++) {
+ func(d->field(i));
+ }
+}
+
+template <class T>
+void ForEachField(const FileDescriptor* d, T&& func) {
+ for (int i = 0; i < d->message_type_count(); i++) {
+ ForEachField(d->message_type(i), std::forward<T&&>(func));
+ }
+ for (int i = 0; i < d->extension_count(); i++) {
+ func(d->extension(i));
+ }
+}
+
+void ListAllTypesForServices(const FileDescriptor* fd,
+ std::vector<const Descriptor*>* types);
+
+// Indicates whether we should use implicit weak fields for this file.
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+ const Options& options);
+
+// Indicates whether to treat this field as implicitly weak.
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+
+inline bool HasSimpleBaseClass(const Descriptor* desc, const Options& options) {
+ if (!HasDescriptorMethods(desc->file(), options)) return false;
+ if (desc->extension_range_count() != 0) return false;
+ if (desc->field_count() == 0) return true;
+ // TODO(jorg): Support additional common message types with only one
+ // or two fields
+ return false;
+}
+
+inline bool HasSimpleBaseClasses(const FileDescriptor* file,
+ const Options& options) {
+ bool v = false;
+ ForEachMessage(file, [&v, &options](const Descriptor* desc) {
+ v |= HasSimpleBaseClass(desc, options);
+ });
+ return v;
+}
+
+inline std::string SimpleBaseClass(const Descriptor* desc,
+ const Options& options) {
+ if (!HasDescriptorMethods(desc->file(), options)) return "";
+ if (desc->extension_range_count() != 0) return "";
+ if (desc->field_count() == 0) {
+ return "ZeroFieldsBase";
+ }
+ // TODO(jorg): Support additional common message types with only one
+ // or two fields
+ return "";
+}
+
+// Formatter is a functor class which acts as a closure around printer and
+// the variable map. It's much like printer->Print except it supports both named
+// variables that are substituted using a key value map and direct arguments. In
+// the format string $1$, $2$, etc... are substituted for the first, second, ...
+// direct argument respectively in the format call, it accepts both strings and
+// integers. The implementation verifies all arguments are used and are "first"
+// used in order of appearance in the argument list. For example,
+//
+// Format("return array[$1$];", 3) -> "return array[3];"
+// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order)
+// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;"
+//
+// The arguments can be used more than once like
+//
+// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") ->
+// "array[3] = Bla; // Index = 3"
+//
+// If you use more arguments use the following style to help the reader,
+//
+// Format("int $1$() {\n"
+// " array[$2$] = $3$;\n"
+// " return $4$;"
+// "}\n",
+// funname, // 1
+// idx, // 2
+// varname, // 3
+// retval); // 4
+//
+// but consider using named variables. Named variables like $foo$, with some
+// identifier foo, are looked up in the map. One additional feature is that
+// spaces are accepted between the '$' delimiters, $ foo$ will
+// substiture to " bar" if foo stands for "bar", but in case it's empty
+// will substitute to "". Hence, for example,
+//
+// Format(vars, "$dllexport $void fun();") -> "void fun();"
+// "__declspec(export) void fun();"
+//
+// which is convenient to prevent double, leading or trailing spaces.
+class PROTOC_EXPORT Formatter {
+ public:
+ explicit Formatter(io::Printer* printer) : printer_(printer) {}
+ Formatter(io::Printer* printer,
+ const std::map<std::string, std::string>& vars)
+ : printer_(printer), vars_(vars) {}
+
+ template <typename T>
+ void Set(const std::string& key, const T& value) {
+ vars_[key] = ToString(value);
+ }
+
+ void AddMap(const std::map<std::string, std::string>& vars) {
+ for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
+ }
+
+ template <typename... Args>
+ void operator()(const char* format, const Args&... args) const {
+ printer_->FormatInternal({ToString(args)...}, vars_, format);
+ }
+
+ void Indent() const { printer_->Indent(); }
+ void Outdent() const { printer_->Outdent(); }
+ io::Printer* printer() const { return printer_; }
+
+ class PROTOC_EXPORT ScopedIndenter {
+ public:
+ explicit ScopedIndenter(Formatter* format) : format_(format) {
+ format_->Indent();
+ }
+ ~ScopedIndenter() { format_->Outdent(); }
+
+ private:
+ Formatter* format_;
+ };
+
+ PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() {
+ return ScopedIndenter(this);
+ }
+ template <typename... Args>
+ PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format,
+ const Args&&... args) {
+ (*this)(format, static_cast<Args&&>(args)...);
+ return ScopedIndenter(this);
+ }
+
+ class PROTOC_EXPORT SaveState {
+ public:
+ explicit SaveState(Formatter* format)
+ : format_(format), vars_(format->vars_) {}
+ ~SaveState() { format_->vars_.swap(vars_); }
+
+ private:
+ Formatter* format_;
+ std::map<std::string, std::string> vars_;
+ };
+
+ private:
+ io::Printer* printer_;
+ std::map<std::string, std::string> vars_;
+
+ // Convenience overloads to accept different types as arguments.
+ static std::string ToString(const std::string& s) { return s; }
+ template <typename I, typename = typename std::enable_if<
+ std::is_integral<I>::value>::type>
+ static std::string ToString(I x) {
+ return StrCat(x);
+ }
+ static std::string ToString(strings::Hex x) { return StrCat(x); }
+ static std::string ToString(const FieldDescriptor* d) { return Payload(d); }
+ static std::string ToString(const Descriptor* d) { return Payload(d); }
+ static std::string ToString(const EnumDescriptor* d) { return Payload(d); }
+ static std::string ToString(const EnumValueDescriptor* d) {
+ return Payload(d);
+ }
+ static std::string ToString(const OneofDescriptor* d) { return Payload(d); }
+
+ template <typename Descriptor>
+ static std::string Payload(const Descriptor* descriptor) {
+ std::vector<int> path;
+ descriptor->GetLocationPath(&path);
+ GeneratedCodeInfo::Annotation annotation;
+ for (int index : path) {
+ annotation.add_path(index);
+ }
+ annotation.set_source_file(descriptor->file()->name());
+ return annotation.SerializeAsString();
+ }
+};
+
+template <class T>
+void PrintFieldComment(const Formatter& format, const T* field) {
+ // Print the field's (or oneof's) proto-syntax definition as a comment.
+ // We don't want to print group bodies so we cut off after the first
+ // line.
+ DebugStringOptions options;
+ options.elide_group_body = true;
+ options.elide_oneof_body = true;
+ std::string def = field->DebugStringWithOptions(options);
+ format("// $1$\n", def.substr(0, def.find_first_of('\n')));
+}
+
+class PROTOC_EXPORT NamespaceOpener {
+ public:
+ explicit NamespaceOpener(const Formatter& format)
+ : printer_(format.printer()) {}
+ NamespaceOpener(const std::string& name, const Formatter& format)
+ : NamespaceOpener(format) {
+ ChangeTo(name);
+ }
+ ~NamespaceOpener() { ChangeTo(""); }
+
+ void ChangeTo(const std::string& name) {
+ std::vector<std::string> new_stack_ =
+ Split(name, "::", true);
+ size_t len = std::min(name_stack_.size(), new_stack_.size());
+ size_t common_idx = 0;
+ while (common_idx < len) {
+ if (name_stack_[common_idx] != new_stack_[common_idx]) break;
+ common_idx++;
+ }
+ for (auto it = name_stack_.crbegin();
+ it != name_stack_.crend() - common_idx; ++it) {
+ if (*it == "PROTOBUF_NAMESPACE_ID") {
+ printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n");
+ } else {
+ printer_->Print("} // namespace $ns$\n", "ns", *it);
+ }
+ }
+ name_stack_.swap(new_stack_);
+ for (size_t i = common_idx; i < name_stack_.size(); ++i) {
+ if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") {
+ printer_->Print("PROTOBUF_NAMESPACE_OPEN\n");
+ } else {
+ printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
+ }
+ }
+ }
+
+ private:
+ io::Printer* printer_;
+ std::vector<std::string> name_stack_;
+};
+
+enum class Utf8CheckMode {
+ kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields.
+ kVerify = 1, // Only log an error but parsing will succeed.
+ kNone = 2, // No UTF-8 check.
+};
+
+Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+ const Options& options);
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format);
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const char* parameters,
+ const Formatter& format);
+
+template <typename T>
+struct FieldRangeImpl {
+ struct Iterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const FieldDescriptor*;
+ using difference_type = int;
+
+ value_type operator*() { return descriptor->field(idx); }
+
+ friend bool operator==(const Iterator& a, const Iterator& b) {
+ GOOGLE_DCHECK(a.descriptor == b.descriptor);
+ return a.idx == b.idx;
+ }
+ friend bool operator!=(const Iterator& a, const Iterator& b) {
+ return !(a == b);
+ }
+
+ Iterator& operator++() {
+ idx++;
+ return *this;
+ }
+
+ int idx;
+ const T* descriptor;
+ };
+
+ Iterator begin() const { return {0, descriptor}; }
+ Iterator end() const { return {descriptor->field_count(), descriptor}; }
+
+ const T* descriptor;
+};
+
+template <typename T>
+FieldRangeImpl<T> FieldRange(const T* desc) {
+ return {desc};
+}
+
+struct OneOfRangeImpl {
+ struct Iterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const OneofDescriptor*;
+ using difference_type = int;
+
+ value_type operator*() { return descriptor->oneof_decl(idx); }
+
+ friend bool operator==(const Iterator& a, const Iterator& b) {
+ GOOGLE_DCHECK(a.descriptor == b.descriptor);
+ return a.idx == b.idx;
+ }
+ friend bool operator!=(const Iterator& a, const Iterator& b) {
+ return !(a == b);
+ }
+
+ Iterator& operator++() {
+ idx++;
+ return *this;
+ }
+
+ int idx;
+ const Descriptor* descriptor;
+ };
+
+ Iterator begin() const { return {0, descriptor}; }
+ Iterator end() const {
+ return {descriptor->real_oneof_decl_count(), descriptor};
+ }
+
+ const Descriptor* descriptor;
+};
+
+inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; }
+
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+bool EnableMessageOwnedArena(const Descriptor* desc);
+
+bool ShouldVerify(const Descriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+bool ShouldVerify(const FileDescriptor* file, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.cc
new file mode 100644
index 00000000..3626a360
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.cc
@@ -0,0 +1,334 @@
+// 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 <compiler/cpp/cpp_map_field.h>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <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<std::string, std::string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
+ (*variables)["type"] = ClassName(descriptor->message_type(), false);
+ (*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(options, key->cpp_type());
+ switch (val->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ (*variables)["val_cpp"] = FieldMessageTypeName(val, options);
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ (*variables)["val_cpp"] = ClassName(val->enum_type(), true);
+ break;
+ default:
+ (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
+ }
+ (*variables)["key_wire_type"] =
+ "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
+ (*variables)["val_wire_type"] =
+ "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
+ (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
+ (*variables)["number"] = StrCat(descriptor->number());
+ (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
+
+ if (HasDescriptorMethods(descriptor->file(), options)) {
+ (*variables)["lite"] = "";
+ } else {
+ (*variables)["lite"] = "Lite";
+ }
+}
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : FieldGenerator(descriptor, options),
+ has_required_fields_(
+ scc_analyzer->HasRequiredFields(descriptor->message_type())) {
+ SetMessageVariables(descriptor, &variables_, options);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "::$proto_ns$::internal::MapField$lite$<\n"
+ " $map_classname$,\n"
+ " $key_cpp$, $val_cpp$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
+ "$name$_;\n");
+}
+
+void MapFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "private:\n"
+ "const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+ " ${1$_internal_$name$$}$() const;\n"
+ "::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+ " ${1$_internal_mutable_$name$$}$();\n"
+ "public:\n"
+ "$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+ " ${1$$name$$}$() const;\n"
+ "$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+ " ${1$mutable_$name$$}$();\n",
+ descriptor_);
+}
+
+void MapFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+ "$classname$::_internal_$name$() const {\n"
+ " return $name$_.GetMap();\n"
+ "}\n"
+ "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n"
+ "$classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_map:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+ "$classname$::_internal_mutable_$name$() {\n"
+ " return $name$_.MutableMap();\n"
+ "}\n"
+ "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ "$annotate_mutable$"
+ " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
+ " return _internal_mutable_$name$();\n"
+ "}\n");
+}
+
+void MapFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.Clear();\n");
+}
+
+void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.InternalSwap(&other->$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ GenerateConstructorCode(printer);
+ GenerateMergingCode(printer);
+}
+
+static void GenerateSerializationLoop(const Formatter& format, bool string_key,
+ bool string_value,
+ bool is_deterministic) {
+ std::string ptr;
+ if (is_deterministic) {
+ format("for (size_type i = 0; i < n; i++) {\n");
+ ptr = string_key ? "items[static_cast<ptrdiff_t>(i)]"
+ : "items[static_cast<ptrdiff_t>(i)].second";
+ } else {
+ format(
+ "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+ " it = this->_internal_$name$().begin();\n"
+ " it != this->_internal_$name$().end(); ++it) {\n");
+ ptr = "it";
+ }
+ format.Indent();
+
+ format(
+ "target = $map_classname$::Funcs::InternalSerialize($number$, "
+ "$1$->first, $1$->second, target, stream);\n",
+ ptr);
+
+ if (string_key || string_value) {
+ // ptr is either an actual pointer or an iterator, either way we can
+ // create a pointer by taking the address after de-referencing it.
+ format("Utf8Check::Check(&(*$1$));\n", ptr);
+ }
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("if (!this->_internal_$name$().empty()) {\n");
+ format.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;
+
+ format(
+ "typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
+ " ConstPtr;\n");
+ if (string_key) {
+ format(
+ "typedef ConstPtr SortItem;\n"
+ "typedef ::$proto_ns$::internal::"
+ "CompareByDerefFirst<SortItem> Less;\n");
+ } else {
+ format(
+ "typedef ::$proto_ns$::internal::SortItem< $key_cpp$, ConstPtr > "
+ "SortItem;\n"
+ "typedef ::$proto_ns$::internal::CompareByFirstField<SortItem> "
+ "Less;\n");
+ }
+ bool utf8_check = string_key || string_value;
+ if (utf8_check) {
+ format(
+ "struct Utf8Check {\n"
+ " static void Check(ConstPtr p) {\n"
+ // p may be unused when GetUtf8CheckMode evaluates to kNone,
+ // thus disabling the validation.
+ " (void)p;\n");
+ format.Indent();
+ format.Indent();
+ if (string_key) {
+ GenerateUtf8CheckCodeForString(
+ key_field, options_, false,
+ "p->first.data(), static_cast<int>(p->first.length()),\n", format);
+ }
+ if (string_value) {
+ GenerateUtf8CheckCodeForString(
+ value_field, options_, false,
+ "p->second.data(), static_cast<int>(p->second.length()),\n", format);
+ }
+ format.Outdent();
+ format.Outdent();
+ format(
+ " }\n"
+ "};\n");
+ }
+
+ format(
+ "\n"
+ "if (stream->IsSerializationDeterministic() &&\n"
+ " this->_internal_$name$().size() > 1) {\n"
+ " ::std::unique_ptr<SortItem[]> items(\n"
+ " new SortItem[this->_internal_$name$().size()]);\n"
+ " typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::size_type "
+ "size_type;\n"
+ " size_type n = 0;\n"
+ " for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+ " it = this->_internal_$name$().begin();\n"
+ " it != this->_internal_$name$().end(); ++it, ++n) {\n"
+ " items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
+ " }\n"
+ " ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
+ format.Indent();
+ GenerateSerializationLoop(format, string_key, string_value, true);
+ format.Outdent();
+ format("} else {\n");
+ format.Indent();
+ GenerateSerializationLoop(format, string_key, string_value, false);
+ format.Outdent();
+ format("}\n");
+ format.Outdent();
+ format("}\n");
+}
+
+void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$ *\n"
+ " "
+ "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
+ "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+ " it = this->_internal_$name$().begin();\n"
+ " it != this->_internal_$name$().end(); ++it) {\n"
+ " total_size += $map_classname$::Funcs::ByteSizeLong(it->first, "
+ "it->second);\n"
+ "}\n");
+}
+
+void MapFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
+ if (!has_required_fields_) return;
+
+ Formatter format(printer, variables_);
+ format(
+ "if (!::$proto_ns$::internal::AllAreInitialized($name$_)) return "
+ "false;\n");
+}
+
+void MapFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
+ } else {
+ format("$name$_()");
+ }
+}
+
+bool MapFieldGenerator::GenerateArenaDestructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ // _this is the object being destructed (we are inside a static method
+ // here).
+ format("_this->$name$_. ~MapField();\n");
+ return true;
+ } else {
+ return false;
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.h
new file mode 100644
index 00000000..8287e536
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_map_field.h
@@ -0,0 +1,78 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_message_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+ MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~MapFieldGenerator() override;
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override {}
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateIsInitialized(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+ bool GenerateArenaDestructorCode(io::Printer* printer) const override;
+
+ private:
+ const bool has_required_fields_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.cc
new file mode 100644
index 00000000..b541017f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.cc
@@ -0,0 +1,4584 @@
+// 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 <compiler/cpp/cpp_message.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <memory>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <stubs/common.h>
+#include <compiler/cpp/cpp_enum.h>
+#include <compiler/cpp/cpp_extension.h>
+#include <compiler/cpp/cpp_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_padding_optimizer.h>
+#include <compiler/cpp/cpp_parse_function_generator.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <descriptor.h>
+#include <generated_message_table_driven.h>
+#include <generated_message_util.h>
+#include <map_entry_lite.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <stubs/hash.h>
+
+
+// Must be included last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+static constexpr int kNoHasbit = -1;
+
+// Create an expression that evaluates to
+// "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
+// masks is allowed to be shorter than _has_bits_, but at least one element of
+// masks must be non-zero.
+std::string ConditionalToCheckBitmasks(
+ const std::vector<uint32_t>& masks, bool return_success = true,
+ StringPiece has_bits_var = "_has_bits_") {
+ std::vector<std::string> parts;
+ for (int i = 0; i < masks.size(); i++) {
+ if (masks[i] == 0) continue;
+ std::string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8));
+ // Each xor evaluates to 0 if the expected bits are present.
+ parts.push_back(
+ StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")"));
+ }
+ GOOGLE_CHECK(!parts.empty());
+ // If we have multiple parts, each expected to be 0, then bitwise-or them.
+ std::string result =
+ parts.size() == 1
+ ? parts[0]
+ : StrCat("(", Join(parts, "\n | "), ")");
+ return result + (return_success ? " == 0" : " != 0");
+}
+
+void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field,
+ const std::vector<int>& has_bit_indices,
+ io::Printer* printer, int* cached_has_word_index) {
+ if (!field->options().weak()) {
+ int has_bit_index = has_bit_indices[field->index()];
+ if (*cached_has_word_index != (has_bit_index / 32)) {
+ *cached_has_word_index = (has_bit_index / 32);
+ format("cached_has_bits = _has_bits_[$1$];\n", *cached_has_word_index);
+ }
+ const std::string mask =
+ StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+ format("if (cached_has_bits & 0x$1$u) {\n", mask);
+ } else {
+ format("if (has_$1$()) {\n", FieldName(field));
+ }
+ format.Indent();
+}
+
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+std::vector<const FieldDescriptor*> SortFieldsByNumber(
+ const Descriptor* descriptor) {
+ std::vector<const FieldDescriptor*> fields(descriptor->field_count());
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields.begin(), fields.end(), FieldOrderingByNumber());
+ return fields;
+}
+
+// Functor for sorting extension ranges by their "start" field number.
+struct ExtensionRangeSorter {
+ bool operator()(const Descriptor::ExtensionRange* left,
+ const Descriptor::ExtensionRange* right) const {
+ return left->start < right->start;
+ }
+};
+
+bool IsPOD(const FieldDescriptor* field) {
+ if (field->is_repeated() || field->is_extension()) return false;
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_INT32:
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT32:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return true;
+ case FieldDescriptor::CPPTYPE_STRING:
+ return false;
+ default:
+ return false;
+ }
+}
+
+// Helper for the code that emits the SharedCtor() and InternalSwap() methods.
+// Anything that is a POD or a "normal" message (represented by a pointer) can
+// be manipulated as raw bytes.
+bool CanBeManipulatedAsRawBytes(const FieldDescriptor* field,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ bool ret = CanInitializeByZeroing(field);
+
+ // Non-repeated, non-lazy message fields are simply raw pointers, so we can
+ // swap them or use memset to initialize these in SharedCtor. We cannot use
+ // this in Clear, as we need to potentially delete the existing value.
+ ret =
+ ret || (!field->is_repeated() && !IsLazy(field, options, scc_analyzer) &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+ return ret;
+}
+
+bool StrContains(const std::string& haystack, const std::string& needle) {
+ return haystack.find(needle) != std::string::npos;
+}
+
+// Finds runs of fields for which `predicate` is true.
+// RunMap maps from fields that start each run to the number of fields in that
+// run. This is optimized for the common case that there are very few runs in
+// a message and that most of the eligible fields appear together.
+using RunMap = std::unordered_map<const FieldDescriptor*, size_t>;
+RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields,
+ const std::function<bool(const FieldDescriptor*)>& predicate) {
+ RunMap runs;
+ const FieldDescriptor* last_start = nullptr;
+
+ for (auto field : fields) {
+ if (predicate(field)) {
+ if (last_start == nullptr) {
+ last_start = field;
+ }
+
+ runs[last_start]++;
+ } else {
+ last_start = nullptr;
+ }
+ }
+ return runs;
+}
+
+// Emits an if-statement with a condition that evaluates to true if |field| is
+// considered non-default (will be sent over the wire), for message types
+// without true field presence. Should only be called if
+// !HasHasbit(field).
+bool EmitFieldNonDefaultCondition(io::Printer* printer,
+ const std::string& prefix,
+ const FieldDescriptor* field) {
+ GOOGLE_CHECK(!HasHasbit(field));
+ Formatter format(printer);
+ format.Set("prefix", prefix);
+ format.Set("name", FieldName(field));
+ // Merge and serialize semantics: primitive fields are merged/serialized only
+ // if non-zero (numeric) or non-empty (string).
+ if (!field->is_repeated() && !field->containing_oneof()) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ format("if (!$prefix$_internal_$name$().empty()) {\n");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message fields still have has_$name$() methods.
+ format("if ($prefix$_internal_has_$name$()) {\n");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) {
+ format(
+ "static_assert(sizeof(uint32_t) == sizeof(float), \"Code assumes "
+ "uint32_t and float are the same size.\");\n"
+ "float tmp_$name$ = $prefix$_internal_$name$();\n"
+ "uint32_t raw_$name$;\n"
+ "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
+ "if (raw_$name$ != 0) {\n");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+ format(
+ "static_assert(sizeof(uint64_t) == sizeof(double), \"Code assumes "
+ "uint64_t and double are the same size.\");\n"
+ "double tmp_$name$ = $prefix$_internal_$name$();\n"
+ "uint64_t raw_$name$;\n"
+ "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
+ "if (raw_$name$ != 0) {\n");
+ } else {
+ format("if ($prefix$_internal_$name$() != 0) {\n");
+ }
+ format.Indent();
+ return true;
+ } else if (field->real_containing_oneof()) {
+ format("if (_internal_has_$name$()) {\n");
+ format.Indent();
+ return true;
+ }
+ return false;
+}
+
+// Does the given field have a has_$name$() method?
+bool HasHasMethod(const FieldDescriptor* field) {
+ if (!IsProto3(field->file())) {
+ // In proto1/proto2, every field has a has_$name$() method.
+ return true;
+ }
+ // For message types without true field presence, only fields with a message
+ // type or inside an one-of have a has_$name$() method.
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ field->has_optional_keyword() || field->real_containing_oneof();
+}
+
+// Collects map entry message type information.
+void CollectMapInfo(const Options& options, const Descriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ GOOGLE_CHECK(IsMapEntryMessage(descriptor));
+ std::map<std::string, std::string>& vars = *variables;
+ const FieldDescriptor* key = descriptor->FindFieldByName("key");
+ const FieldDescriptor* val = descriptor->FindFieldByName("value");
+ vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type());
+ switch (val->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ vars["val_cpp"] = FieldMessageTypeName(val, options);
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ vars["val_cpp"] = ClassName(val->enum_type(), true);
+ break;
+ default:
+ vars["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
+ }
+ vars["key_wire_type"] =
+ "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
+ vars["val_wire_type"] =
+ "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
+}
+
+// Does the given field have a private (internal helper only) has_$name$()
+// method?
+bool HasPrivateHasMethod(const FieldDescriptor* field) {
+ // Only for oneofs in message types with no field presence. has_$name$(),
+ // based on the oneof case, is still useful internally for generated code.
+ return IsProto3(field->file()) && field->real_containing_oneof();
+}
+
+// TODO(ckennelly): Cull these exclusions if/when these protos do not have
+// their methods overridden by subclasses.
+
+bool ShouldMarkClassAsFinal(const Descriptor* descriptor,
+ const Options& options) {
+ return true;
+}
+
+
+// Returns true to make the message serialize in order, decided by the following
+// factors in the order of precedence.
+// --options().message_set_wire_format() == true
+// --the message is in the allowlist (true)
+// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false)
+// --a ranage of message names that are allowed to stay in order (true)
+bool ShouldSerializeInOrder(const Descriptor* descriptor,
+ const Options& options) {
+ return true;
+}
+
+bool TableDrivenParsingEnabled(const Descriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ if (!options.table_driven_parsing) {
+ return false;
+ }
+
+ // Consider table-driven parsing. We only do this if:
+ // - We have has_bits for fields. This avoids a check on every field we set
+ // when are present (the common case).
+ bool has_hasbit = false;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (HasHasbit(descriptor->field(i))) {
+ has_hasbit = true;
+ break;
+ }
+ }
+
+ if (!has_hasbit) return false;
+
+ const double table_sparseness = 0.5;
+ int max_field_number = 0;
+ for (auto field : FieldRange(descriptor)) {
+ if (max_field_number < field->number()) {
+ max_field_number = field->number();
+ }
+
+ // - There are no weak fields.
+ if (IsWeak(field, options)) {
+ return false;
+ }
+
+ // - There are no lazy fields (they require the non-lite library).
+ if (IsLazy(field, options, scc_analyzer)) {
+ return false;
+ }
+ }
+
+ // - There range of field numbers is "small"
+ if (max_field_number >= (2 << 14)) {
+ return false;
+ }
+
+ // - Field numbers are relatively dense within the actual number of fields.
+ // We check for strictly greater than in the case where there are no fields
+ // (only extensions) so max_field_number == descriptor->field_count() == 0.
+ if (max_field_number * table_sparseness > descriptor->field_count()) {
+ return false;
+ }
+
+ // - This is not a MapEntryMessage.
+ if (IsMapEntryMessage(descriptor)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool IsCrossFileMapField(const FieldDescriptor* field) {
+ if (!field->is_map()) {
+ return false;
+ }
+
+ const Descriptor* d = field->message_type();
+ const FieldDescriptor* value = d->FindFieldByNumber(2);
+
+ return IsCrossFileMessage(value);
+}
+
+bool IsCrossFileMaybeMap(const FieldDescriptor* field) {
+ if (IsCrossFileMapField(field)) {
+ return true;
+ }
+
+ return IsCrossFileMessage(field);
+}
+
+bool IsRequired(const std::vector<const FieldDescriptor*>& v) {
+ return v.front()->is_required();
+}
+
+bool HasSingularString(const Descriptor* desc, const Options& options) {
+ for (const auto* field : FieldRange(desc)) {
+ if (IsString(field, options) && !IsStringInlined(field, options) &&
+ !field->is_repeated() && !field->real_containing_oneof()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Collects neighboring fields based on a given criteria (equivalent predicate).
+template <typename Predicate>
+std::vector<std::vector<const FieldDescriptor*>> CollectFields(
+ const std::vector<const FieldDescriptor*>& fields,
+ const Predicate& equivalent) {
+ std::vector<std::vector<const FieldDescriptor*>> chunks;
+ for (auto field : fields) {
+ if (chunks.empty() || !equivalent(chunks.back().back(), field)) {
+ chunks.emplace_back();
+ }
+ chunks.back().push_back(field);
+ }
+ return chunks;
+}
+
+// Returns a bit mask based on has_bit index of "fields" that are typically on
+// the same chunk. It is used in a group presence check where _has_bits_ is
+// masked to tell if any thing in "fields" is present.
+uint32_t GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
+ const std::vector<int>& has_bit_indices) {
+ GOOGLE_CHECK(!fields.empty());
+ int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
+ uint32_t chunk_mask = 0;
+ for (auto field : fields) {
+ // "index" defines where in the _has_bits_ the field appears.
+ int index = has_bit_indices[field->index()];
+ GOOGLE_CHECK_EQ(first_index_offset, index / 32);
+ chunk_mask |= static_cast<uint32_t>(1) << (index % 32);
+ }
+ GOOGLE_CHECK_NE(0, chunk_mask);
+ return chunk_mask;
+}
+
+// Return the number of bits set in n, a non-negative integer.
+static int popcnt(uint32_t n) {
+ int result = 0;
+ while (n != 0) {
+ result += (n & 1);
+ n = n / 2;
+ }
+ return result;
+}
+
+// For a run of cold chunks, opens and closes an external if statement that
+// checks multiple has_bits words to skip bulk of cold fields.
+class ColdChunkSkipper {
+ public:
+ ColdChunkSkipper(
+ const Options& options,
+ const std::vector<std::vector<const FieldDescriptor*>>& chunks,
+ const std::vector<int>& has_bit_indices, const double cold_threshold)
+ : chunks_(chunks),
+ has_bit_indices_(has_bit_indices),
+ access_info_map_(options.access_info_map),
+ cold_threshold_(cold_threshold) {
+ SetCommonVars(options, &variables_);
+ }
+
+ // May open an external if check for a batch of cold fields. "from" is the
+ // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_".
+ // Otherwise, it should be "".
+ void OnStartChunk(int chunk, int cached_has_word_index,
+ const std::string& from, io::Printer* printer);
+ bool OnEndChunk(int chunk, io::Printer* printer);
+
+ private:
+ bool IsColdChunk(int chunk);
+
+ int HasbitWord(int chunk, int offset) {
+ return has_bit_indices_[chunks_[chunk][offset]->index()] / 32;
+ }
+
+ const std::vector<std::vector<const FieldDescriptor*>>& chunks_;
+ const std::vector<int>& has_bit_indices_;
+ const AccessInfoMap* access_info_map_;
+ const double cold_threshold_;
+ std::map<std::string, std::string> variables_;
+ int limit_chunk_ = -1;
+};
+
+// Tuning parameters for ColdChunkSkipper.
+const double kColdRatio = 0.005;
+
+bool ColdChunkSkipper::IsColdChunk(int chunk) {
+ // Mark this variable as used until it is actually used
+ (void)cold_threshold_;
+ return false;
+}
+
+
+void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
+ const std::string& from,
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (!access_info_map_) {
+ return;
+ } else if (chunk < limit_chunk_) {
+ // We are already inside a run of cold chunks.
+ return;
+ } else if (!IsColdChunk(chunk)) {
+ // We can't start a run of cold chunks.
+ return;
+ }
+
+ // Find the end of consecutive cold chunks.
+ limit_chunk_ = chunk;
+ while (limit_chunk_ < chunks_.size() && IsColdChunk(limit_chunk_)) {
+ limit_chunk_++;
+ }
+
+ if (limit_chunk_ <= chunk + 1) {
+ // Require at least two chunks to emit external has_bit checks.
+ limit_chunk_ = -1;
+ return;
+ }
+
+ // Emit has_bit check for each has_bit_dword index.
+ format("if (PROTOBUF_PREDICT_FALSE(");
+ int first_word = HasbitWord(chunk, 0);
+ while (chunk < limit_chunk_) {
+ uint32_t mask = 0;
+ int this_word = HasbitWord(chunk, 0);
+ // Generate mask for chunks on the same word.
+ for (; chunk < limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) {
+ for (auto field : chunks_[chunk]) {
+ int hasbit_index = has_bit_indices_[field->index()];
+ // Fields on a chunk must be in the same word.
+ GOOGLE_CHECK_EQ(this_word, hasbit_index / 32);
+ mask |= 1 << (hasbit_index % 32);
+ }
+ }
+
+ if (this_word != first_word) {
+ format(" ||\n ");
+ }
+ format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8));
+ if (this_word == cached_has_word_index) {
+ format("(cached_has_bits & 0x$mask$u) != 0");
+ } else {
+ format("($1$_has_bits_[$2$] & 0x$mask$u) != 0", from, this_word);
+ }
+ }
+ format(")) {\n");
+ format.Indent();
+}
+
+bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (chunk != limit_chunk_ - 1) {
+ return false;
+ }
+ format.Outdent();
+ format("}\n");
+ return true;
+}
+
+void MaySetAnnotationVariable(const Options& options,
+ StringPiece annotation_name,
+ StringPiece injector_template_prefix,
+ StringPiece injector_template_suffix,
+ std::map<std::string, std::string>* variables) {
+ if (options.field_listener_options.forbidden_field_listener_events.count(
+ std::string(annotation_name)))
+ return;
+ (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute(
+ StrCat(injector_template_prefix, injector_template_suffix),
+ (*variables)["classtype"]);
+}
+
+void GenerateExtensionAnnotations(
+ const Descriptor* descriptor, const Options& options,
+ std::map<std::string, std::string>* variables) {
+ const std::map<std::string, std::string> accessor_annotations_to_hooks = {
+ {"annotate_extension_has", "OnHasExtension"},
+ {"annotate_extension_clear", "OnClearExtension"},
+ {"annotate_extension_repeated_size", "OnExtensionSize"},
+ {"annotate_extension_get", "OnGetExtension"},
+ {"annotate_extension_mutable", "OnMutableExtension"},
+ {"annotate_extension_set", "OnSetExtension"},
+ {"annotate_extension_release", "OnReleaseExtension"},
+ {"annotate_repeated_extension_get", "OnGetExtension"},
+ {"annotate_repeated_extension_mutable", "OnMutableExtension"},
+ {"annotate_repeated_extension_set", "OnSetExtension"},
+ {"annotate_repeated_extension_add", "OnAddExtension"},
+ {"annotate_repeated_extension_add_mutable", "OnAddMutableExtension"},
+ {"annotate_repeated_extension_list", "OnListExtension"},
+ {"annotate_repeated_extension_list_mutable", "OnMutableListExtension"},
+ };
+ for (const auto& annotation : accessor_annotations_to_hooks) {
+ (*variables)[annotation.first] = "";
+ }
+ if (!options.field_listener_options.inject_field_listener_events ||
+ descriptor->file()->options().optimize_for() ==
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ return;
+ }
+ for (const auto& annotation : accessor_annotations_to_hooks) {
+ const std::string& annotation_name = annotation.first;
+ const std::string& listener_call = annotation.second;
+ if (!StrContains(annotation_name, "repeated") &&
+ !StrContains(annotation_name, "size") &&
+ !StrContains(annotation_name, "clear")) {
+ // Primitive fields accessors.
+ // "Has" is here as users calling "has" on a repeated field is a mistake.
+ (*variables)[annotation_name] = StrCat(
+ " _tracker_.", listener_call,
+ "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), "
+ "_extensions_, id.default_value_ref()));");
+ } else if (StrContains(annotation_name, "repeated") &&
+ !StrContains(annotation_name, "list") &&
+ !StrContains(annotation_name, "size")) {
+ // Repeated index accessors.
+ std::string str_index = "index";
+ if (StrContains(annotation_name, "add")) {
+ str_index = "_extensions_.ExtensionSize(id.number()) - 1";
+ }
+ (*variables)[annotation_name] =
+ StrCat(" _tracker_.", listener_call,
+ "(this, id.number(), "
+ "_proto_TypeTraits::GetPtr(id.number(), _extensions_, ",
+ str_index, "));");
+ } else if (StrContains(annotation_name, "list") ||
+ StrContains(annotation_name, "size")) {
+ // Repeated full accessors.
+ (*variables)[annotation_name] = StrCat(
+ " _tracker_.", listener_call,
+ "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), "
+ "_extensions_));");
+ } else {
+ // Generic accessors such as "clear".
+ // TODO(b/190614678): Generalize clear from both repeated and non repeated
+ // calls, currently their underlying memory interfaces are very different.
+ // Or think of removing clear callback as no usages are needed and no
+ // memory exist after calling clear().
+ }
+ }
+}
+
+} // anonymous namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(
+ const Descriptor* descriptor,
+ const std::map<std::string, std::string>& vars, int index_in_file_messages,
+ const Options& options, MessageSCCAnalyzer* scc_analyzer)
+ : descriptor_(descriptor),
+ index_in_file_messages_(index_in_file_messages),
+ classname_(ClassName(descriptor, false)),
+ options_(options),
+ field_generators_(descriptor, options, scc_analyzer),
+ max_has_bit_index_(0),
+ max_inlined_string_index_(0),
+ num_weak_fields_(0),
+ scc_analyzer_(scc_analyzer),
+ variables_(vars) {
+ if (!message_layout_helper_) {
+ message_layout_helper_.reset(new PaddingOptimizer());
+ }
+
+ // Variables that apply to this class
+ variables_["classname"] = classname_;
+ variables_["classtype"] = QualifiedClassName(descriptor_, options);
+ variables_["full_name"] = descriptor_->full_name();
+ variables_["superclass"] = SuperClassName(descriptor_, options_);
+ variables_["annotate_serialize"] = "";
+ variables_["annotate_deserialize"] = "";
+ variables_["annotate_reflection"] = "";
+ variables_["annotate_bytesize"] = "";
+ variables_["annotate_mergefrom"] = "";
+
+ if (options.field_listener_options.inject_field_listener_events &&
+ descriptor->file()->options().optimize_for() !=
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ const std::string injector_template = " _tracker_.";
+
+ MaySetAnnotationVariable(options, "serialize", injector_template,
+ "OnSerialize(this);\n", &variables_);
+ MaySetAnnotationVariable(options, "deserialize", injector_template,
+ "OnDeserialize(this);\n", &variables_);
+ // TODO(danilak): Ideally annotate_reflection should not exist and we need
+ // to annotate all reflective calls on our own, however, as this is a cause
+ // for side effects, i.e. reading values dynamically, we want the users know
+ // that dynamic access can happen.
+ MaySetAnnotationVariable(options, "reflection", injector_template,
+ "OnGetMetadata();\n", &variables_);
+ MaySetAnnotationVariable(options, "bytesize", injector_template,
+ "OnByteSize(this);\n", &variables_);
+ MaySetAnnotationVariable(options, "mergefrom", injector_template,
+ "OnMergeFrom(this, &from);\n", &variables_);
+ }
+
+ GenerateExtensionAnnotations(descriptor_, options_, &variables_);
+
+ SetUnknownFieldsVariable(descriptor_, options_, &variables_);
+
+ // Compute optimized field order to be used for layout and initialization
+ // purposes.
+ for (auto field : FieldRange(descriptor_)) {
+ if (IsFieldStripped(field, options_)) {
+ continue;
+ }
+
+ if (IsWeak(field, options_)) {
+ num_weak_fields_++;
+ } else if (!field->real_containing_oneof()) {
+ optimized_order_.push_back(field);
+ }
+ }
+
+ message_layout_helper_->OptimizeLayout(&optimized_order_, options_,
+ scc_analyzer_);
+
+ // This message has hasbits iff one or more fields need one.
+ for (auto field : optimized_order_) {
+ if (HasHasbit(field)) {
+ if (has_bit_indices_.empty()) {
+ has_bit_indices_.resize(descriptor_->field_count(), kNoHasbit);
+ }
+ has_bit_indices_[field->index()] = max_has_bit_index_++;
+ }
+ if (IsStringInlined(field, options_)) {
+ if (inlined_string_indices_.empty()) {
+ inlined_string_indices_.resize(descriptor_->field_count(), kNoHasbit);
+ }
+ inlined_string_indices_[field->index()] = max_inlined_string_index_++;
+ }
+ }
+
+ if (!has_bit_indices_.empty()) {
+ field_generators_.SetHasBitIndices(has_bit_indices_);
+ }
+
+ if (!inlined_string_indices_.empty()) {
+ field_generators_.SetInlinedStringIndices(inlined_string_indices_);
+ }
+
+ num_required_fields_ = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_required()) {
+ ++num_required_fields_;
+ }
+ }
+
+ table_driven_ =
+ TableDrivenParsingEnabled(descriptor_, options_, scc_analyzer_);
+ parse_function_generator_.reset(new ParseFunctionGenerator(
+ descriptor_, max_has_bit_index_, has_bit_indices_,
+ inlined_string_indices_, options_, scc_analyzer_, variables_));
+}
+
+MessageGenerator::~MessageGenerator() = default;
+
+size_t MessageGenerator::HasBitsSize() const {
+ return (max_has_bit_index_ + 31) / 32;
+}
+
+size_t MessageGenerator::InlinedStringDonatedSize() const {
+ return (max_inlined_string_index_ + 31) / 32;
+}
+
+int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
+ return has_bit_indices_.empty() ? kNoHasbit
+ : has_bit_indices_[field->index()];
+}
+
+int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const {
+ int hasbit = HasBitIndex(field);
+ return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8;
+}
+
+int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const {
+ int hasbit = HasBitIndex(field);
+ return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32;
+}
+
+void MessageGenerator::AddGenerators(
+ std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
+ std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ enum_generators->emplace_back(
+ new EnumGenerator(descriptor_->enum_type(i), variables_, options_));
+ enum_generators_.push_back(enum_generators->back().get());
+ }
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators->emplace_back(new ExtensionGenerator(
+ descriptor_->extension(i), options_, scc_analyzer_));
+ extension_generators_.push_back(extension_generators->back().get());
+ }
+}
+
+void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ // optimized_fields_ does not contain fields where
+ // field->real_containing_oneof()
+ // so we need to iterate over those as well.
+ //
+ // We place the non-oneof fields in optimized_order_, as that controls the
+ // order of the _has_bits_ entries and we want GDB's pretty printers to be
+ // able to infer these indices from the k[FIELDNAME]FieldNumber order.
+ std::vector<const FieldDescriptor*> ordered_fields;
+ ordered_fields.reserve(descriptor_->field_count());
+
+ ordered_fields.insert(ordered_fields.begin(), optimized_order_.begin(),
+ optimized_order_.end());
+ for (auto field : FieldRange(descriptor_)) {
+ if (!field->real_containing_oneof() && !field->options().weak() &&
+ !IsFieldStripped(field, options_)) {
+ continue;
+ }
+ ordered_fields.push_back(field);
+ }
+
+ if (!ordered_fields.empty()) {
+ format("enum : int {\n");
+ for (auto field : ordered_fields) {
+ Formatter::SaveState save(&format);
+
+ std::map<std::string, std::string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ format.AddMap(vars);
+ format(" ${1$$2$$}$ = $number$,\n", field, FieldConstantName(field));
+ }
+ format("};\n");
+ }
+ for (auto field : ordered_fields) {
+ PrintFieldComment(format, field);
+
+ Formatter::SaveState save(&format);
+
+ std::map<std::string, std::string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ format.AddMap(vars);
+
+ if (field->is_repeated()) {
+ format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
+ !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
+ if (!IsFieldStripped(field, options_)) {
+ format(
+ "private:\n"
+ "int ${1$_internal_$name$_size$}$() const;\n"
+ "public:\n",
+ field);
+ }
+ } else if (HasHasMethod(field)) {
+ format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
+ !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
+ if (!IsFieldStripped(field, options_)) {
+ format(
+ "private:\n"
+ "bool _internal_has_$name$() const;\n"
+ "public:\n");
+ }
+ } else if (HasPrivateHasMethod(field)) {
+ if (!IsFieldStripped(field, options_)) {
+ format(
+ "private:\n"
+ "bool ${1$_internal_has_$name$$}$() const;\n"
+ "public:\n",
+ field);
+ }
+ }
+ format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
+ !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
+
+ // Generate type-specific accessor declarations.
+ field_generators_.get(field).GenerateAccessorDeclarations(printer);
+
+ format("\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ // Generate accessors for extensions.
+ // We use "_proto_TypeTraits" as a type name below because "TypeTraits"
+ // causes problems if the class has a nested message or enum type with that
+ // name and "_TypeTraits" is technically reserved for the C++ library since
+ // it starts with an underscore followed by a capital letter.
+ //
+ // For similar reason, we use "_field_type" and "_is_packed" as parameter
+ // names below, so that "field_type" and "is_packed" can be used as field
+ // names.
+ format(R"(
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline bool HasExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
+$annotate_extension_has$
+ return _extensions_.Has(id.number());
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void ClearExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+ _extensions_.ClearExtension(id.number());
+$annotate_extension_clear$
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline int ExtensionSize(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
+$annotate_extension_repeated_size$
+ return _extensions_.ExtensionSize(id.number());
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Singular::ConstType GetExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
+$annotate_extension_get$
+ return _proto_TypeTraits::Get(id.number(), _extensions_,
+ id.default_value());
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Singular::MutableType MutableExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+$annotate_extension_mutable$
+ return _proto_TypeTraits::Mutable(id.number(), _field_type,
+ &_extensions_);
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void SetExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ typename _proto_TypeTraits::Singular::ConstType value) {
+ _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_);
+$annotate_extension_set$
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void SetAllocatedExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ typename _proto_TypeTraits::Singular::MutableType value) {
+ _proto_TypeTraits::SetAllocated(id.number(), _field_type, value,
+ &_extensions_);
+$annotate_extension_set$
+}
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void UnsafeArenaSetAllocatedExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ typename _proto_TypeTraits::Singular::MutableType value) {
+ _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type,
+ value, &_extensions_);
+$annotate_extension_set$
+}
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+PROTOBUF_NODISCARD inline
+ typename _proto_TypeTraits::Singular::MutableType
+ ReleaseExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+$annotate_extension_release$
+ return _proto_TypeTraits::Release(id.number(), _field_type,
+ &_extensions_);
+}
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Singular::MutableType
+UnsafeArenaReleaseExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+$annotate_extension_release$
+ return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type,
+ &_extensions_);
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Repeated::ConstType GetExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ int index) const {
+$annotate_repeated_extension_get$
+ return _proto_TypeTraits::Get(id.number(), _extensions_, index);
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ int index) {
+$annotate_repeated_extension_mutable$
+ return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_);
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void SetExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ int index, typename _proto_TypeTraits::Repeated::ConstType value) {
+ _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
+$annotate_repeated_extension_set$
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Repeated::MutableType AddExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+ typename _proto_TypeTraits::Repeated::MutableType to_add =
+ _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_);
+$annotate_repeated_extension_add_mutable$
+ return to_add;
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline void AddExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
+ typename _proto_TypeTraits::Repeated::ConstType value) {
+ _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value,
+ &_extensions_);
+$annotate_repeated_extension_add$
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType&
+GetRepeatedExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
+$annotate_repeated_extension_list$
+ return _proto_TypeTraits::GetRepeated(id.number(), _extensions_);
+}
+
+template <typename _proto_TypeTraits,
+ ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
+ bool _is_packed>
+inline typename _proto_TypeTraits::Repeated::RepeatedFieldType*
+MutableRepeatedExtension(
+ const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
+ $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
+$annotate_repeated_extension_list_mutable$
+ return _proto_TypeTraits::MutableRepeated(id.number(), _field_type,
+ _is_packed, &_extensions_);
+}
+
+)");
+ // Generate MessageSet specific APIs for proto2 MessageSet.
+ // For testing purposes we don't check for bridge.MessageSet, so
+ // we don't use IsProto2MessageSet
+ if (descriptor_->options().message_set_wire_format() &&
+ !options_.opensource_runtime && !options_.lite_implicit_weak_fields) {
+ // Special-case MessageSet
+ format("GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($classname$)\n");
+ }
+ }
+
+ for (auto oneof : OneOfRange(descriptor_)) {
+ Formatter::SaveState saver(&format);
+ format.Set("oneof_name", oneof->name());
+ format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true));
+ format(
+ "void ${1$clear_$oneof_name$$}$();\n"
+ "$camel_oneof_name$Case $oneof_name$_case() const;\n",
+ oneof);
+ }
+}
+
+void MessageGenerator::GenerateSingularFieldHasBits(
+ const FieldDescriptor* field, Formatter format) {
+ if (IsFieldStripped(field, options_)) {
+ format(
+ "inline bool $classname$::has_$name$() const { "
+ "__builtin_trap(); }\n");
+ return;
+ }
+ if (field->options().weak()) {
+ format(
+ "inline bool $classname$::has_$name$() const {\n"
+ "$annotate_has$"
+ " return _weak_field_map_.Has($number$);\n"
+ "}\n");
+ return;
+ }
+ if (HasHasbit(field)) {
+ int has_bit_index = HasBitIndex(field);
+ GOOGLE_CHECK_NE(has_bit_index, kNoHasbit);
+
+ format.Set("has_array_index", has_bit_index / 32);
+ format.Set("has_mask",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+ format(
+ "inline bool $classname$::_internal_has_$name$() const {\n"
+ " bool value = "
+ "(_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n");
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !IsLazy(field, options_, scc_analyzer_)) {
+ // We maintain the invariant that for a submessage x, has_x() returning
+ // true implies that x_ is not null. By giving this information to the
+ // compiler, we allow it to eliminate unnecessary null checks later on.
+ format(" PROTOBUF_ASSUME(!value || $name$_ != nullptr);\n");
+ }
+
+ format(
+ " return value;\n"
+ "}\n"
+ "inline bool $classname$::has_$name$() const {\n"
+ "$annotate_has$"
+ " return _internal_has_$name$();\n"
+ "}\n");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message fields have a has_$name$() method.
+ if (IsLazy(field, options_, scc_analyzer_)) {
+ format(
+ "inline bool $classname$::_internal_has_$name$() const {\n"
+ " return !$name$_.IsCleared();\n"
+ "}\n");
+ } else {
+ format(
+ "inline bool $classname$::_internal_has_$name$() const {\n"
+ " return this != internal_default_instance() "
+ "&& $name$_ != nullptr;\n"
+ "}\n");
+ }
+ format(
+ "inline bool $classname$::has_$name$() const {\n"
+ "$annotate_has$"
+ " return _internal_has_$name$();\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format.Set("oneof_name", oneof->name());
+ format.Set("oneof_index", oneof->index());
+ format.Set("cap_oneof_name", ToUpper(oneof->name()));
+ format(
+ "inline bool $classname$::has_$oneof_name$() const {\n"
+ " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
+ "}\n"
+ "inline void $classname$::clear_has_$oneof_name$() {\n"
+ " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const Formatter& format) {
+ if (IsFieldStripped(field, options_)) {
+ if (HasHasMethod(field)) {
+ format(
+ "inline bool $classname$::has_$name$() const { "
+ "__builtin_trap(); }\n");
+ }
+ format(
+ "inline void $classname$::set_has_$name$() { __builtin_trap(); "
+ "}\n");
+ return;
+ }
+ // Singular field in a oneof
+ // N.B.: Without field presence, we do not use has-bits or generate
+ // has_$name$() methods, but oneofs still have set_has_$name$().
+ // Oneofs also have has_$name$() but only as a private helper
+ // method, so that generated code is slightly cleaner (vs. comparing
+ // _oneof_case_[index] against a constant everywhere).
+ //
+ // If has_$name$() is private, there is no need to add an internal accessor.
+ // Only annotate public accessors.
+ if (HasHasMethod(field)) {
+ format(
+ "inline bool $classname$::_internal_has_$name$() const {\n"
+ " return $oneof_name$_case() == k$field_name$;\n"
+ "}\n"
+ "inline bool $classname$::has_$name$() const {\n"
+ "$annotate_has$"
+ " return _internal_has_$name$();\n"
+ "}\n");
+ } else if (HasPrivateHasMethod(field)) {
+ format(
+ "inline bool $classname$::_internal_has_$name$() const {\n"
+ " return $oneof_name$_case() == k$field_name$;\n"
+ "}\n");
+ }
+ // set_has_$name$() for oneof fields is always private; hence should not be
+ // annotated.
+ format(
+ "inline void $classname$::set_has_$name$() {\n"
+ " _oneof_case_[$oneof_index$] = k$field_name$;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
+ bool is_inline, Formatter format) {
+ if (IsFieldStripped(field, options_)) {
+ format("void $classname$::clear_$name$() { __builtin_trap(); }\n");
+ return;
+ }
+
+ // Generate clear_$name$().
+ if (is_inline) {
+ format("inline ");
+ }
+ format("void $classname$::clear_$name$() {\n");
+
+ format.Indent();
+
+ if (field->real_containing_oneof()) {
+ // Clear this field only if it is the active field in this oneof,
+ // otherwise ignore
+ format("if (_internal_has_$name$()) {\n");
+ format.Indent();
+ field_generators_.get(field).GenerateClearingCode(format.printer());
+ format("clear_has_$oneof_name$();\n");
+ format.Outdent();
+ format("}\n");
+ } else {
+ field_generators_.get(field).GenerateClearingCode(format.printer());
+ if (HasHasbit(field)) {
+ int has_bit_index = HasBitIndex(field);
+ format.Set("has_array_index", has_bit_index / 32);
+ format.Set("has_mask",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+ format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
+ }
+ }
+ format("$annotate_clear$");
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format("// $classname$\n\n");
+
+ for (auto field : FieldRange(descriptor_)) {
+ PrintFieldComment(format, field);
+
+ if (IsFieldStripped(field, options_)) {
+ continue;
+ }
+
+ std::map<std::string, std::string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+
+ Formatter::SaveState saver(&format);
+ format.AddMap(vars);
+
+ // Generate has_$name$() or $name$_size().
+ if (field->is_repeated()) {
+ if (IsFieldStripped(field, options_)) {
+ format(
+ "inline int $classname$::$name$_size() const { "
+ "__builtin_trap(); }\n");
+ } else {
+ format(
+ "inline int $classname$::_internal_$name$_size() const {\n"
+ " return $name$_$1$.size();\n"
+ "}\n"
+ "inline int $classname$::$name$_size() const {\n"
+ "$annotate_size$"
+ " return _internal_$name$_size();\n"
+ "}\n",
+ IsImplicitWeakField(field, options_, scc_analyzer_) &&
+ field->message_type()
+ ? ".weak"
+ : "");
+ }
+ } else if (field->real_containing_oneof()) {
+ format.Set("field_name", UnderscoresToCamelCase(field->name(), true));
+ format.Set("oneof_name", field->containing_oneof()->name());
+ format.Set("oneof_index",
+ StrCat(field->containing_oneof()->index()));
+ GenerateOneofMemberHasBits(field, format);
+ } else {
+ // Singular field.
+ GenerateSingularFieldHasBits(field, format);
+ }
+
+ if (!IsCrossFileMaybeMap(field)) {
+ GenerateFieldClear(field, true, format);
+ }
+
+ // Generate type-specific accessors.
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
+ }
+
+ format("\n");
+ }
+
+ // Generate has_$name$() and clear_has_$name$() functions for oneofs.
+ GenerateOneofHasBits(printer);
+}
+
+void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format.Set("class_final",
+ ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : "");
+
+ if (IsMapEntryMessage(descriptor_)) {
+ std::map<std::string, std::string> vars;
+ CollectMapInfo(options_, descriptor_, &vars);
+ vars["lite"] =
+ HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite";
+ format.AddMap(vars);
+ format(
+ "class $classname$ : public "
+ "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
+ " $key_cpp$, $val_cpp$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
+ "public:\n"
+ " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
+ " $key_cpp$, $val_cpp$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
+ " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
+ "SuperType;\n"
+ " $classname$();\n"
+ " explicit constexpr $classname$(\n"
+ " ::$proto_ns$::internal::ConstantInitialized);\n"
+ " explicit $classname$(::$proto_ns$::Arena* arena);\n"
+ " void MergeFrom(const $classname$& other);\n"
+ " static const $classname$* internal_default_instance() { return "
+ "reinterpret_cast<const "
+ "$classname$*>(&_$classname$_default_instance_); }\n");
+ auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_);
+ if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
+ utf8_check != Utf8CheckMode::kNone) {
+ if (utf8_check == Utf8CheckMode::kStrict) {
+ format(
+ " static bool ValidateKey(std::string* s) {\n"
+ " return ::$proto_ns$::internal::WireFormatLite::"
+ "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
+ "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
+ " }\n",
+ descriptor_->field(0)->full_name());
+ } else {
+ GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
+ format(
+ " static bool ValidateKey(std::string* s) {\n"
+ "#ifndef NDEBUG\n"
+ " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
+ " s->data(), static_cast<int>(s->size()), "
+ "::$proto_ns$::internal::"
+ "WireFormatLite::PARSE, \"$1$\");\n"
+ "#else\n"
+ " (void) s;\n"
+ "#endif\n"
+ " return true;\n"
+ " }\n",
+ descriptor_->field(0)->full_name());
+ }
+ } else {
+ format(" static bool ValidateKey(void*) { return true; }\n");
+ }
+ if (descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING &&
+ utf8_check != Utf8CheckMode::kNone) {
+ if (utf8_check == Utf8CheckMode::kStrict) {
+ format(
+ " static bool ValidateValue(std::string* s) {\n"
+ " return ::$proto_ns$::internal::WireFormatLite::"
+ "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
+ "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
+ " }\n",
+ descriptor_->field(1)->full_name());
+ } else {
+ GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
+ format(
+ " static bool ValidateValue(std::string* s) {\n"
+ "#ifndef NDEBUG\n"
+ " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
+ " s->data(), static_cast<int>(s->size()), "
+ "::$proto_ns$::internal::"
+ "WireFormatLite::PARSE, \"$1$\");\n"
+ "#else\n"
+ " (void) s;\n"
+ "#endif\n"
+ " return true;\n"
+ " }\n",
+ descriptor_->field(1)->full_name());
+ }
+ } else {
+ format(" static bool ValidateValue(void*) { return true; }\n");
+ }
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ " using ::$proto_ns$::Message::MergeFrom;\n"
+ ""
+ " ::$proto_ns$::Metadata GetMetadata() const final;\n");
+ }
+ format("};\n");
+ return;
+ }
+
+ format(
+ "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n"
+ " public $superclass$ /* @@protoc_insertion_point("
+ "class_definition:$full_name$) */ {\n",
+ descriptor_);
+ format(" public:\n");
+ format.Indent();
+
+ if (EnableMessageOwnedArena(descriptor_)) {
+ format(
+ "inline $classname$() : $classname$("
+ "::$proto_ns$::Arena::InternalHelper<$classname$>::\n"
+ " CreateMessageOwnedArena(), true) {}\n");
+ } else {
+ format("inline $classname$() : $classname$(nullptr) {}\n");
+ }
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format("~$classname$() override;\n");
+ }
+ format(
+ "explicit constexpr "
+ "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
+ "\n"
+ "$classname$(const $classname$& from);\n"
+ "$classname$($classname$&& from) noexcept\n"
+ " : $classname$() {\n"
+ " *this = ::std::move(from);\n"
+ "}\n"
+ "\n"
+ "inline $classname$& operator=(const $classname$& from) {\n"
+ " CopyFrom(from);\n"
+ " return *this;\n"
+ "}\n"
+ "inline $classname$& operator=($classname$&& from) noexcept {\n"
+ " if (this == &from) return *this;\n"
+ " if (GetOwningArena() == from.GetOwningArena()\n"
+ "#ifdef PROTOBUF_FORCE_COPY_IN_MOVE\n"
+ " && GetOwningArena() != nullptr\n"
+ "#endif // !PROTOBUF_FORCE_COPY_IN_MOVE\n"
+ " ) {\n"
+ " InternalSwap(&from);\n"
+ " } else {\n"
+ " CopyFrom(from);\n"
+ " }\n"
+ " return *this;\n"
+ "}\n"
+ "\n");
+
+ if (options_.table_driven_serialization) {
+ format(
+ "private:\n"
+ "const void* InternalGetTable() const override;\n"
+ "public:\n"
+ "\n");
+ }
+
+ if (PublicUnknownFieldsAccessors(descriptor_)) {
+ format(
+ "inline const $unknown_fields_type$& unknown_fields() const {\n"
+ " return $unknown_fields$;\n"
+ "}\n"
+ "inline $unknown_fields_type$* mutable_unknown_fields() {\n"
+ " return $mutable_unknown_fields$;\n"
+ "}\n"
+ "\n");
+ }
+
+ // Only generate this member if it's not disabled.
+ if (HasDescriptorMethods(descriptor_->file(), options_) &&
+ !descriptor_->options().no_standard_descriptor_accessor()) {
+ format(
+ "static const ::$proto_ns$::Descriptor* descriptor() {\n"
+ " return GetDescriptor();\n"
+ "}\n");
+ }
+
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ // These shadow non-static methods of the same names in Message. We
+ // redefine them here because calls directly on the generated class can be
+ // statically analyzed -- we know what descriptor types are being requested.
+ // It also avoids a vtable dispatch.
+ //
+ // We would eventually like to eliminate the methods in Message, and having
+ // this separate also lets us track calls to the base class methods
+ // separately.
+ format(
+ "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
+ " return default_instance().GetMetadata().descriptor;\n"
+ "}\n"
+ "static const ::$proto_ns$::Reflection* GetReflection() {\n"
+ " return default_instance().GetMetadata().reflection;\n"
+ "}\n");
+ }
+
+ format(
+ "static const $classname$& default_instance() {\n"
+ " return *internal_default_instance();\n"
+ "}\n");
+
+ // Generate enum values for every field in oneofs. One list is generated for
+ // each oneof with an additional *_NOT_SET value.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("enum $1$Case {\n", UnderscoresToCamelCase(oneof->name(), true));
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ format("$1$ = $2$,\n", OneofCaseConstantName(field), // 1
+ field->number()); // 2
+ }
+ format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name()));
+ format.Outdent();
+ format(
+ "};\n"
+ "\n");
+ }
+
+ // TODO(gerbens) make this private, while still granting other protos access.
+ format(
+ "static inline const $classname$* internal_default_instance() {\n"
+ " return reinterpret_cast<const $classname$*>(\n"
+ " &_$classname$_default_instance_);\n"
+ "}\n"
+ "static constexpr int kIndexInFileMessages =\n"
+ " $1$;\n"
+ "\n",
+ index_in_file_messages_);
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ format(
+ "// implements Any -----------------------------------------------\n"
+ "\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "bool PackFrom(const ::$proto_ns$::Message& message) {\n"
+ " return _any_metadata_.PackFrom(GetArena(), message);\n"
+ "}\n"
+ "bool PackFrom(const ::$proto_ns$::Message& message,\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+ "type_url_prefix) {\n"
+ " return _any_metadata_.PackFrom(GetArena(), message, "
+ "type_url_prefix);\n"
+ "}\n"
+ "bool UnpackTo(::$proto_ns$::Message* message) const {\n"
+ " return _any_metadata_.UnpackTo(message);\n"
+ "}\n"
+ "static bool GetAnyFieldDescriptors(\n"
+ " const ::$proto_ns$::Message& message,\n"
+ " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
+ " const ::$proto_ns$::FieldDescriptor** value_field);\n"
+ "template <typename T, class = typename std::enable_if<"
+ "!std::is_convertible<T, const ::$proto_ns$::Message&>"
+ "::value>::type>\n"
+ "bool PackFrom(const T& message) {\n"
+ " return _any_metadata_.PackFrom<T>(GetArena(), message);\n"
+ "}\n"
+ "template <typename T, class = typename std::enable_if<"
+ "!std::is_convertible<T, const ::$proto_ns$::Message&>"
+ "::value>::type>\n"
+ "bool PackFrom(const T& message,\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+ "type_url_prefix) {\n"
+ " return _any_metadata_.PackFrom<T>(GetArena(), message, "
+ "type_url_prefix);"
+ "}\n"
+ "template <typename T, class = typename std::enable_if<"
+ "!std::is_convertible<T, const ::$proto_ns$::Message&>"
+ "::value>::type>\n"
+ "bool UnpackTo(T* message) const {\n"
+ " return _any_metadata_.UnpackTo<T>(message);\n"
+ "}\n");
+ } else {
+ format(
+ "template <typename T>\n"
+ "bool PackFrom(const T& message) {\n"
+ " return _any_metadata_.PackFrom(GetArena(), message);\n"
+ "}\n"
+ "template <typename T>\n"
+ "bool PackFrom(const T& message,\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+ "type_url_prefix) {\n"
+ " return _any_metadata_.PackFrom(GetArena(), message, "
+ "type_url_prefix);\n"
+ "}\n"
+ "template <typename T>\n"
+ "bool UnpackTo(T* message) const {\n"
+ " return _any_metadata_.UnpackTo(message);\n"
+ "}\n");
+ }
+ format(
+ "template<typename T> bool Is() const {\n"
+ " return _any_metadata_.Is<T>();\n"
+ "}\n"
+ "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
+ "type_url,\n"
+ " std::string* full_type_name);\n");
+ }
+
+ format(
+ "friend void swap($classname$& a, $classname$& b) {\n"
+ " a.Swap(&b);\n"
+ "}\n"
+ "inline void Swap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ "#ifdef PROTOBUF_FORCE_COPY_IN_SWAP\n"
+ " if (GetOwningArena() != nullptr &&\n"
+ " GetOwningArena() == other->GetOwningArena()) {\n "
+ "#else // PROTOBUF_FORCE_COPY_IN_SWAP\n"
+ " if (GetOwningArena() == other->GetOwningArena()) {\n"
+ "#endif // !PROTOBUF_FORCE_COPY_IN_SWAP\n"
+ " InternalSwap(other);\n"
+ " } else {\n"
+ " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
+ " }\n"
+ "}\n"
+ "void UnsafeArenaSwap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
+ " InternalSwap(other);\n"
+ "}\n");
+
+ format(
+ "\n"
+ "// implements Message ----------------------------------------------\n"
+ "\n"
+ "$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
+ " return CreateMaybeMessage<$classname$>(arena);\n"
+ "}\n");
+
+ // For instances that derive from Message (rather than MessageLite), some
+ // methods are virtual and should be marked as final.
+ format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_)
+ ? "final"
+ : "");
+
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ // Use Message's built-in MergeFrom and CopyFrom when the passed-in
+ // argument is a generic Message instance, and only define the
+ // custom MergeFrom and CopyFrom instances when the source of the
+ // merge/copy is known to be the same class as the destination.
+ // TODO(jorg): Define MergeFrom in terms of MergeImpl, rather than
+ // the other way around, to save even more code size.
+ "using $superclass$::CopyFrom;\n"
+ "void CopyFrom(const $classname$& from);\n"
+ ""
+ "using $superclass$::MergeFrom;\n"
+ "void MergeFrom(const $classname$& from);\n"
+ "private:\n"
+ "static void MergeImpl(::$proto_ns$::Message* to, const "
+ "::$proto_ns$::Message& from);\n"
+ "public:\n");
+ } else {
+ format(
+ "using $superclass$::CopyFrom;\n"
+ "inline void CopyFrom(const $classname$& from) {\n"
+ " $superclass$::CopyImpl(this, from);\n"
+ "}\n"
+ ""
+ "using $superclass$::MergeFrom;\n"
+ "void MergeFrom(const $classname$& from) {\n"
+ " $superclass$::MergeImpl(this, from);\n"
+ "}\n"
+ "public:\n");
+ }
+ } else {
+ format(
+ "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)"
+ " final;\n"
+ "void CopyFrom(const $classname$& from);\n"
+ "void MergeFrom(const $classname$& from);\n");
+ }
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n"
+ "bool IsInitialized() const final;\n"
+ "\n"
+ "size_t ByteSizeLong() const final;\n");
+
+ parse_function_generator_->GenerateMethodDecls(printer);
+
+ format(
+ "$uint8$* _InternalSerialize(\n"
+ " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
+ "const final;\n");
+ }
+ }
+
+ if (options_.field_listener_options.inject_field_listener_events) {
+ format("static constexpr int _kInternalFieldNumber = $1$;\n",
+ descriptor_->field_count());
+ }
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ "int GetCachedSize() const final { return _cached_size_.Get(); }"
+ "\n\nprivate:\n"
+ "void SharedCtor();\n"
+ "void SharedDtor();\n"
+ "void SetCachedSize(int size) const$ full_final$;\n"
+ "void InternalSwap($classname$* other);\n");
+ }
+
+ format(
+ // Friend AnyMetadata so that it can call this FullMessageName() method.
+ "\nprivate:\n"
+ "friend class ::$proto_ns$::internal::AnyMetadata;\n"
+ "static $1$ FullMessageName() {\n"
+ " return \"$full_name$\";\n"
+ "}\n",
+ options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
+ : "::StringPiece");
+
+ format(
+ // TODO(gerbens) Make this private! Currently people are deriving from
+ // protos to give access to this constructor, breaking the invariants
+ // we rely on.
+ "protected:\n"
+ "explicit $classname$(::$proto_ns$::Arena* arena,\n"
+ " bool is_message_owned = false);\n"
+ "private:\n");
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ "static void ArenaDtor(void* object);\n"
+ "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
+ }
+
+ format(
+ "public:\n"
+ "\n");
+
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ format(
+ "static const ClassData _class_data_;\n"
+ "const ::$proto_ns$::Message::ClassData*"
+ "GetClassData() const final;\n"
+ "\n");
+ }
+ format(
+ "::$proto_ns$::Metadata GetMetadata() const final;\n"
+ "\n");
+ } else {
+ format(
+ "std::string GetTypeName() const final;\n"
+ "\n");
+ }
+
+ format(
+ "// nested types ----------------------------------------------------\n"
+ "\n");
+
+ // Import all nested message classes into this class's scope with typedefs.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ const Descriptor* nested_type = descriptor_->nested_type(i);
+ if (!IsMapEntryMessage(nested_type)) {
+ format.Set("nested_full_name", ClassName(nested_type, false));
+ format.Set("nested_name", ResolveKeyword(nested_type->name()));
+ format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n",
+ nested_type);
+ }
+ }
+
+ if (descriptor_->nested_type_count() > 0) {
+ format("\n");
+ }
+
+ // Import all nested enums and their values into this class's scope with
+ // typedefs and constants.
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateSymbolImports(printer);
+ format("\n");
+ }
+
+ format(
+ "// accessors -------------------------------------------------------\n"
+ "\n");
+
+ // Generate accessor methods for all fields.
+ GenerateFieldAccessorDeclarations(printer);
+
+ // Declare extension identifiers.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_[i]->GenerateDeclaration(printer);
+ }
+
+
+ format("// @@protoc_insertion_point(class_scope:$full_name$)\n");
+
+ // Generate private members.
+ format.Outdent();
+ format(" private:\n");
+ format.Indent();
+ // TODO(seongkim): Remove hack to track field access and remove this class.
+ format("class _Internal;\n");
+
+ for (auto field : FieldRange(descriptor_)) {
+ // set_has_***() generated in all oneofs.
+ if (!field->is_repeated() && !field->options().weak() &&
+ field->real_containing_oneof()) {
+ format("void set_has_$1$();\n", FieldName(field));
+ }
+ }
+ format("\n");
+
+ // Generate oneof function declarations
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format(
+ "inline bool has_$1$() const;\n"
+ "inline void clear_has_$1$();\n\n",
+ oneof->name());
+ }
+
+ if (HasGeneratedMethods(descriptor_->file(), options_) &&
+ !descriptor_->options().message_set_wire_format() &&
+ num_required_fields_ > 1) {
+ format(
+ "// helper for ByteSizeLong()\n"
+ "size_t RequiredFieldsByteSizeFallback() const;\n\n");
+ }
+
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ parse_function_generator_->GenerateDataDecls(printer);
+ }
+
+ // Prepare decls for _cached_size_ and _has_bits_. Their position in the
+ // output will be determined later.
+
+ bool need_to_emit_cached_size = true;
+ const std::string cached_size_decl =
+ "mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n";
+
+ const size_t sizeof_has_bits = HasBitsSize();
+ const std::string has_bits_decl =
+ sizeof_has_bits == 0 ? ""
+ : StrCat("::$proto_ns$::internal::HasBits<",
+ sizeof_has_bits, "> _has_bits_;\n");
+
+ // To minimize padding, data members are divided into three sections:
+ // (1) members assumed to align to 8 bytes
+ // (2) members corresponding to message fields, re-ordered to optimize
+ // alignment.
+ // (3) members assumed to align to 4 bytes.
+
+ // Members assumed to align to 8 bytes:
+
+ if (descriptor_->extension_range_count() > 0) {
+ format(
+ "::$proto_ns$::internal::ExtensionSet _extensions_;\n"
+ "\n");
+ }
+
+ if (options_.field_listener_options.inject_field_listener_events &&
+ descriptor_->file()->options().optimize_for() !=
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ format("static ::$proto_ns$::AccessListener<$1$> _tracker_;\n",
+ ClassName(descriptor_));
+ }
+
+ // Generate _inlined_string_donated_ for inlined string type.
+ // TODO(congliu): To avoid affecting the locality of `_has_bits_`, should this
+ // be below or above `_has_bits_`?
+ if (!inlined_string_indices_.empty()) {
+ format("::$proto_ns$::internal::HasBits<$1$> _inlined_string_donated_;\n",
+ InlinedStringDonatedSize());
+ }
+
+ format(
+ "template <typename T> friend class "
+ "::$proto_ns$::Arena::InternalHelper;\n"
+ "typedef void InternalArenaConstructable_;\n"
+ "typedef void DestructorSkippable_;\n");
+
+ if (!has_bit_indices_.empty()) {
+ // _has_bits_ is frequently accessed, so to reduce code size and improve
+ // speed, it should be close to the start of the object. Placing
+ // _cached_size_ together with _has_bits_ improves cache locality despite
+ // potential alignment padding.
+ format(has_bits_decl.c_str());
+ format(cached_size_decl.c_str());
+ need_to_emit_cached_size = false;
+ }
+
+ // Field members:
+
+ // Emit some private and static members
+ for (auto field : optimized_order_) {
+ const FieldGenerator& generator = field_generators_.get(field);
+ generator.GenerateStaticMembers(printer);
+ generator.GeneratePrivateMembers(printer);
+ }
+
+ // For each oneof generate a union
+ for (auto oneof : OneOfRange(descriptor_)) {
+ std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true);
+ format("union $1$Union {\n", camel_oneof_name);
+ format.Indent();
+ format(
+ // explicit empty constructor is needed when union contains
+ // ArenaStringPtr members for string fields.
+ "constexpr $1$Union() : _constinit_{} {}\n"
+ " ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
+ camel_oneof_name);
+ for (auto field : FieldRange(oneof)) {
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GeneratePrivateMembers(printer);
+ }
+ }
+ format.Outdent();
+ format("} $1$_;\n", oneof->name());
+ for (auto field : FieldRange(oneof)) {
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateStaticMembers(printer);
+ }
+ }
+ }
+
+ // Members assumed to align to 4 bytes:
+
+ if (need_to_emit_cached_size) {
+ format(cached_size_decl.c_str());
+ need_to_emit_cached_size = false;
+ }
+
+ // Generate _oneof_case_.
+ if (descriptor_->real_oneof_decl_count() > 0) {
+ format(
+ "$uint32$ _oneof_case_[$1$];\n"
+ "\n",
+ descriptor_->real_oneof_decl_count());
+ }
+
+ if (num_weak_fields_) {
+ format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n");
+ }
+ // Generate _any_metadata_ for the Any type.
+ if (IsAnyMessage(descriptor_, options_)) {
+ format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n");
+ }
+
+ // The TableStruct struct needs access to the private parts, in order to
+ // construct the offsets of all members.
+ format("friend struct ::$tablename$;\n");
+
+ format.Outdent();
+ format("};");
+ GOOGLE_DCHECK(!need_to_emit_cached_size);
+} // NOLINT(readability/fn_size)
+
+void MessageGenerator::GenerateInlineMethods(io::Printer* printer) {
+ if (IsMapEntryMessage(descriptor_)) return;
+ GenerateFieldAccessorDefinitions(printer);
+
+ // Generate oneof_case() functions.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ Formatter format(printer, variables_);
+ format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true));
+ format.Set("oneof_name", oneof->name());
+ format.Set("oneof_index", oneof->index());
+ format(
+ "inline $classname$::$camel_oneof_name$Case $classname$::"
+ "${1$$oneof_name$_case$}$() const {\n"
+ " return $classname$::$camel_oneof_name$Case("
+ "_oneof_case_[$oneof_index$]);\n"
+ "}\n",
+ oneof);
+ }
+}
+
+bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
+ size_t aux_offset) {
+ Formatter format(printer, variables_);
+
+ if (!table_driven_) {
+ format("{ nullptr, nullptr, 0, -1, -1, -1, -1, nullptr, false },\n");
+ return false;
+ }
+
+ int max_field_number = 0;
+ for (auto field : FieldRange(descriptor_)) {
+ if (max_field_number < field->number()) {
+ max_field_number = field->number();
+ }
+ }
+
+ format("{\n");
+ format.Indent();
+
+ format(
+ "$tablename$::entries + $1$,\n"
+ "$tablename$::aux + $2$,\n"
+ "$3$,\n",
+ offset, aux_offset, max_field_number);
+
+ if (has_bit_indices_.empty()) {
+ // If no fields have hasbits, then _has_bits_ does not exist.
+ format("-1,\n");
+ } else {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
+ }
+
+ if (descriptor_->real_oneof_decl_count() > 0) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_),\n");
+ } else {
+ format("-1, // no _oneof_case_\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n");
+ } else {
+ format("-1, // no _extensions_\n");
+ }
+
+ // TODO(ckennelly): Consolidate this with the calculation for
+ // AuxiliaryParseTableField.
+ format(
+ "PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n"
+ "&$package_ns$::_$classname$_default_instance_,\n");
+
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+ format("true,\n");
+ } else {
+ format("false,\n");
+ }
+
+ format.Outdent();
+ format("},\n");
+ return true;
+}
+
+void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
+ int has_offset) {
+ Formatter format(printer, variables_);
+ has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)
+ ? offset + has_offset
+ : -1;
+ int inlined_string_indices_offset;
+ if (inlined_string_indices_.empty()) {
+ inlined_string_indices_offset = -1;
+ } else {
+ GOOGLE_DCHECK_NE(has_offset, -1);
+ GOOGLE_DCHECK(!IsMapEntryMessage(descriptor_));
+ inlined_string_indices_offset = has_offset + has_bit_indices_.size();
+ }
+
+ format("{ $1$, $2$, $3$, sizeof($classtype$)},\n", offset, has_offset,
+ inlined_string_indices_offset);
+}
+
+namespace {
+
+// We need to calculate for each field what function the table driven code
+// should use to serialize it. This returns the index in a lookup table.
+uint32_t CalcFieldNum(const FieldGenerator& generator,
+ const FieldDescriptor* field, const Options& options) {
+ bool is_a_map = IsMapEntryMessage(field->containing_type());
+ int type = field->type();
+ if (type == FieldDescriptor::TYPE_STRING ||
+ type == FieldDescriptor::TYPE_BYTES) {
+ // string field
+ if (generator.IsInlined()) {
+ type = internal::FieldMetadata::kInlinedType;
+ } else if (IsCord(field, options)) {
+ type = internal::FieldMetadata::kCordType;
+ } else if (IsStringPiece(field, options)) {
+ type = internal::FieldMetadata::kStringPieceType;
+ }
+ }
+
+ if (field->real_containing_oneof()) {
+ return internal::FieldMetadata::CalculateType(
+ type, internal::FieldMetadata::kOneOf);
+ } else if (field->is_packed()) {
+ return internal::FieldMetadata::CalculateType(
+ type, internal::FieldMetadata::kPacked);
+ } else if (field->is_repeated()) {
+ return internal::FieldMetadata::CalculateType(
+ type, internal::FieldMetadata::kRepeated);
+ } else if (HasHasbit(field) || field->real_containing_oneof() || is_a_map) {
+ return internal::FieldMetadata::CalculateType(
+ type, internal::FieldMetadata::kPresence);
+ } else {
+ return internal::FieldMetadata::CalculateType(
+ type, internal::FieldMetadata::kNoPresence);
+ }
+}
+
+int FindMessageIndexInFile(const Descriptor* descriptor) {
+ std::vector<const Descriptor*> flatten =
+ FlattenMessagesInFile(descriptor->file());
+ return std::find(flatten.begin(), flatten.end(), descriptor) -
+ flatten.begin();
+}
+
+} // namespace
+
+int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (!options_.table_driven_serialization) {
+ return 0;
+ }
+
+ std::vector<const FieldDescriptor*> sorted = SortFieldsByNumber(descriptor_);
+ if (IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < 2; i++) {
+ const FieldDescriptor* field = sorted[i];
+ const FieldGenerator& generator = field_generators_.get(field);
+
+ uint32_t tag = internal::WireFormatLite::MakeTag(
+ field->number(), WireFormat::WireTypeForFieldType(field->type()));
+
+ std::map<std::string, std::string> vars;
+ vars["classtype"] = QualifiedClassName(descriptor_, options_);
+ vars["field_name"] = FieldName(field);
+ vars["tag"] = StrCat(tag);
+ vars["hasbit"] = StrCat(i);
+ vars["type"] = StrCat(CalcFieldNum(generator, field, options_));
+ vars["ptr"] = "nullptr";
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ GOOGLE_CHECK(!IsMapEntryMessage(field->message_type()));
+ vars["ptr"] =
+ "::" + UniqueName("TableStruct", field->message_type(), options_) +
+ "::serialization_table + " +
+ StrCat(FindMessageIndexInFile(field->message_type()));
+ }
+ Formatter::SaveState saver(&format);
+ format.AddMap(vars);
+ format(
+ "{PROTOBUF_FIELD_OFFSET("
+ "::$proto_ns$::internal::MapEntryHelper<$classtype$::"
+ "SuperType>, $field_name$_), $tag$,"
+ "PROTOBUF_FIELD_OFFSET("
+ "::$proto_ns$::internal::MapEntryHelper<$classtype$::"
+ "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, "
+ "$ptr$},\n");
+ }
+ return 2;
+ }
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_),"
+ " 0, 0, 0, nullptr},\n");
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeSorter());
+ for (int i = 0, extension_idx = 0; /* no range */; i++) {
+ for (; extension_idx < sorted_extensions.size() &&
+ (i == sorted.size() ||
+ sorted_extensions[extension_idx]->start < sorted[i]->number());
+ extension_idx++) {
+ const Descriptor::ExtensionRange* range =
+ sorted_extensions[extension_idx];
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, _extensions_), "
+ "$1$, $2$, ::$proto_ns$::internal::FieldMetadata::kSpecial, "
+ "reinterpret_cast<const "
+ "void*>(::$proto_ns$::internal::ExtensionSerializer)},\n",
+ range->start, range->end);
+ }
+ if (i == sorted.size()) break;
+ const FieldDescriptor* field = sorted[i];
+
+ uint32_t tag = internal::WireFormatLite::MakeTag(
+ field->number(), WireFormat::WireTypeForFieldType(field->type()));
+ if (field->is_packed()) {
+ tag = internal::WireFormatLite::MakeTag(
+ field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ std::string classfieldname = FieldName(field);
+ if (field->real_containing_oneof()) {
+ classfieldname = field->containing_oneof()->name();
+ }
+ format.Set("field_name", classfieldname);
+ std::string ptr = "nullptr";
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (IsMapEntryMessage(field->message_type())) {
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$, $2$, "
+ "::$proto_ns$::internal::FieldMetadata::kSpecial, "
+ "reinterpret_cast<const void*>(static_cast< "
+ "::$proto_ns$::internal::SpecialSerializer>("
+ "::$proto_ns$::internal::MapFieldSerializer< "
+ "::$proto_ns$::internal::MapEntryToMapField<"
+ "$3$>::MapFieldType, "
+ "$tablename$::serialization_table>))},\n",
+ tag, FindMessageIndexInFile(field->message_type()),
+ QualifiedClassName(field->message_type(), options_));
+ continue;
+ } else if (!field->message_type()->options().message_set_wire_format()) {
+ // message_set doesn't have the usual table and we need to
+ // dispatch to generated serializer, hence ptr stays zero.
+ ptr =
+ "::" + UniqueName("TableStruct", field->message_type(), options_) +
+ "::serialization_table + " +
+ StrCat(FindMessageIndexInFile(field->message_type()));
+ }
+ }
+
+ const FieldGenerator& generator = field_generators_.get(field);
+ int type = CalcFieldNum(generator, field, options_);
+
+ if (IsLazy(field, options_, scc_analyzer_)) {
+ type = internal::FieldMetadata::kSpecial;
+ ptr = "reinterpret_cast<const void*>(::" + variables_["proto_ns"] +
+ "::internal::LazyFieldSerializer";
+ if (field->real_containing_oneof()) {
+ ptr += "OneOf";
+ } else if (!HasHasbit(field)) {
+ ptr += "NoPresence";
+ }
+ ptr += ")";
+ }
+
+ if (field->options().weak()) {
+ // TODO(gerbens) merge weak fields into ranges
+ format(
+ "{PROTOBUF_FIELD_OFFSET("
+ "$classtype$, _weak_field_map_), $1$, $1$, "
+ "::$proto_ns$::internal::FieldMetadata::kSpecial, "
+ "reinterpret_cast<const "
+ "void*>(::$proto_ns$::internal::WeakFieldSerializer)},\n",
+ tag);
+ } else if (field->real_containing_oneof()) {
+ format.Set("oneofoffset",
+ sizeof(uint32_t) * field->containing_oneof()->index());
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$,"
+ " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
+ "$oneofoffset$, $2$, $3$},\n",
+ tag, type, ptr);
+ } else if (HasHasbit(field)) {
+ format.Set("hasbitsoffset", has_bit_indices_[field->index()]);
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
+ "$1$, PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_) * 8 + "
+ "$hasbitsoffset$, $2$, $3$},\n",
+ tag, type, ptr);
+ } else {
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
+ "$1$, ~0u, $2$, $3$},\n",
+ tag, type, ptr);
+ }
+ }
+ int num_field_metadata = 1 + sorted.size() + sorted_extensions.size();
+ num_field_metadata++;
+ std::string serializer = UseUnknownFieldSet(descriptor_->file(), options_)
+ ? "UnknownFieldSetSerializer"
+ : "UnknownFieldSerializerLite";
+ format(
+ "{PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_), 0, ~0u, "
+ "::$proto_ns$::internal::FieldMetadata::kSpecial, reinterpret_cast<const "
+ "void*>(::$proto_ns$::internal::$1$)},\n",
+ serializer);
+ return num_field_metadata;
+}
+
+void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (IsMapEntryMessage(descriptor_)) {
+ format(
+ "$classname$::$classname$() {}\n"
+ "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
+ " : SuperType(arena) {}\n"
+ "void $classname$::MergeFrom(const $classname$& other) {\n"
+ " MergeFromInternal(other);\n"
+ "}\n");
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ if (!descriptor_->options().map_entry()) {
+ format(
+ "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
+ "$annotate_reflection$"
+ " return ::$proto_ns$::internal::AssignDescriptors(\n"
+ " &$desc_table$_getter, &$desc_table$_once,\n"
+ " $file_level_metadata$[$1$]);\n"
+ "}\n",
+ index_in_file_messages_);
+ } else {
+ format(
+ "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
+ " return ::$proto_ns$::internal::AssignDescriptors(\n"
+ " &$desc_table$_getter, &$desc_table$_once,\n"
+ " $file_level_metadata$[$1$]);\n"
+ "}\n",
+ index_in_file_messages_);
+ }
+ }
+ return;
+ }
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ format(
+ "bool $classname$::GetAnyFieldDescriptors(\n"
+ " const ::$proto_ns$::Message& message,\n"
+ " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
+ " const ::$proto_ns$::FieldDescriptor** value_field) {\n"
+ " return ::$proto_ns$::internal::GetAnyFieldDescriptors(\n"
+ " message, type_url_field, value_field);\n"
+ "}\n");
+ }
+ format(
+ "bool $classname$::ParseAnyTypeUrl(\n"
+ " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
+ " std::string* full_type_name) {\n"
+ " return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n"
+ " full_type_name);\n"
+ "}\n"
+ "\n");
+ }
+
+ format(
+ "class $classname$::_Internal {\n"
+ " public:\n");
+ format.Indent();
+ if (!has_bit_indices_.empty()) {
+ format(
+ "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n");
+ }
+ for (auto field : FieldRange(descriptor_)) {
+ field_generators_.get(field).GenerateInternalAccessorDeclarations(printer);
+ if (IsFieldStripped(field, options_)) {
+ continue;
+ }
+ if (HasHasbit(field)) {
+ int has_bit_index = HasBitIndex(field);
+ GOOGLE_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name();
+ format(
+ "static void set_has_$1$(HasBits* has_bits) {\n"
+ " (*has_bits)[$2$] |= $3$u;\n"
+ "}\n",
+ FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32)));
+ }
+ }
+ if (num_required_fields_ > 0) {
+ const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
+ format(
+ "static bool MissingRequiredFields(const HasBits& has_bits) "
+ "{\n"
+ " return $1$;\n"
+ "}\n",
+ ConditionalToCheckBitmasks(masks_for_has_bits, false, "has_bits"));
+ }
+
+ format.Outdent();
+ format("};\n\n");
+ for (auto field : FieldRange(descriptor_)) {
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateInternalAccessorDefinitions(printer);
+ }
+ }
+
+ // Generate non-inline field definitions.
+ for (auto field : FieldRange(descriptor_)) {
+ if (IsFieldStripped(field, options_)) {
+ continue;
+ }
+ field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer);
+ if (IsCrossFileMaybeMap(field)) {
+ Formatter::SaveState saver(&format);
+ std::map<std::string, std::string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ if (field->real_containing_oneof()) {
+ SetCommonOneofFieldVariables(field, &vars);
+ }
+ format.AddMap(vars);
+ GenerateFieldClear(field, false, format);
+ }
+ }
+
+ GenerateStructors(printer);
+ format("\n");
+
+ if (descriptor_->real_oneof_decl_count() > 0) {
+ GenerateOneofClear(printer);
+ format("\n");
+ }
+
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ GenerateClear(printer);
+ format("\n");
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ parse_function_generator_->GenerateMethodImpls(printer);
+ format("\n");
+
+ parse_function_generator_->GenerateDataDefinitions(printer);
+ }
+
+ GenerateSerializeWithCachedSizesToArray(printer);
+ format("\n");
+
+ GenerateByteSize(printer);
+ format("\n");
+
+ GenerateMergeFrom(printer);
+ format("\n");
+
+ GenerateClassSpecificMergeFrom(printer);
+ format("\n");
+
+ GenerateCopyFrom(printer);
+ format("\n");
+
+ GenerateIsInitialized(printer);
+ format("\n");
+ }
+
+ GenerateVerify(printer);
+
+ GenerateSwap(printer);
+ format("\n");
+
+ if (options_.table_driven_serialization) {
+ format(
+ "const void* $classname$::InternalGetTable() const {\n"
+ " return ::$tablename$::serialization_table + $1$;\n"
+ "}\n"
+ "\n",
+ index_in_file_messages_);
+ }
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ if (!descriptor_->options().map_entry()) {
+ format(
+ "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
+ "$annotate_reflection$"
+ " return ::$proto_ns$::internal::AssignDescriptors(\n"
+ " &$desc_table$_getter, &$desc_table$_once,\n"
+ " $file_level_metadata$[$1$]);\n"
+ "}\n",
+ index_in_file_messages_);
+ } else {
+ format(
+ "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
+ " return ::$proto_ns$::internal::AssignDescriptors(\n"
+ " &$desc_table$_getter, &$desc_table$_once,\n"
+ " $file_level_metadata$[$1$]);\n"
+ "}\n",
+ index_in_file_messages_);
+ }
+ } else {
+ format(
+ "std::string $classname$::GetTypeName() const {\n"
+ " return \"$full_name$\";\n"
+ "}\n"
+ "\n");
+ }
+
+ if (options_.field_listener_options.inject_field_listener_events &&
+ descriptor_->file()->options().optimize_for() !=
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ format(
+ "::$proto_ns$::AccessListener<$classtype$> "
+ "$1$::_tracker_(&FullMessageName);\n",
+ ClassName(descriptor_));
+ }
+}
+
+size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ if (!table_driven_) {
+ return 0;
+ }
+
+ // Field "0" is special: We use it in our switch statement of processing
+ // types to handle the successful end tag case.
+ format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n");
+ int last_field_number = 1;
+
+ std::vector<const FieldDescriptor*> ordered_fields =
+ SortFieldsByNumber(descriptor_);
+
+ for (auto field : ordered_fields) {
+ Formatter::SaveState saver(&format);
+ GOOGLE_CHECK_GE(field->number(), last_field_number);
+
+ for (; last_field_number < field->number(); last_field_number++) {
+ format(
+ "{ 0, 0, ::$proto_ns$::internal::kInvalidMask,\n"
+ " ::$proto_ns$::internal::kInvalidMask, 0, 0 },\n");
+ }
+ last_field_number++;
+
+ unsigned char normal_wiretype, packed_wiretype, processing_type;
+ normal_wiretype = WireFormat::WireTypeForFieldType(field->type());
+
+ if (field->is_packable()) {
+ packed_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+ } else {
+ packed_wiretype = internal::kNotPackedMask;
+ }
+
+ processing_type = static_cast<unsigned>(field->type());
+ const FieldGenerator& generator = field_generators_.get(field);
+ if (field->type() == FieldDescriptor::TYPE_STRING) {
+ switch (EffectiveStringCType(field, options_)) {
+ case FieldOptions::STRING:
+ if (generator.IsInlined()) {
+ processing_type = internal::TYPE_STRING_INLINED;
+ }
+ break;
+ case FieldOptions::CORD:
+ processing_type = internal::TYPE_STRING_CORD;
+ break;
+ case FieldOptions::STRING_PIECE:
+ processing_type = internal::TYPE_STRING_STRING_PIECE;
+ break;
+ }
+ } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ switch (EffectiveStringCType(field, options_)) {
+ case FieldOptions::STRING:
+ if (generator.IsInlined()) {
+ processing_type = internal::TYPE_BYTES_INLINED;
+ }
+ break;
+ case FieldOptions::CORD:
+ processing_type = internal::TYPE_BYTES_CORD;
+ break;
+ case FieldOptions::STRING_PIECE:
+ processing_type = internal::TYPE_BYTES_STRING_PIECE;
+ break;
+ }
+ }
+
+ processing_type |= static_cast<unsigned>(
+ field->is_repeated() ? internal::kRepeatedMask : 0);
+ processing_type |= static_cast<unsigned>(
+ field->real_containing_oneof() ? internal::kOneofMask : 0);
+
+ if (field->is_map()) {
+ processing_type = internal::TYPE_MAP;
+ }
+
+ const unsigned char tag_size =
+ WireFormat::TagSize(field->number(), field->type());
+
+ std::map<std::string, std::string> vars;
+ if (field->real_containing_oneof()) {
+ vars["name"] = field->containing_oneof()->name();
+ vars["presence"] = StrCat(field->containing_oneof()->index());
+ } else {
+ vars["name"] = FieldName(field);
+ vars["presence"] = StrCat(has_bit_indices_[field->index()]);
+ }
+ vars["nwtype"] = StrCat(normal_wiretype);
+ vars["pwtype"] = StrCat(packed_wiretype);
+ vars["ptype"] = StrCat(processing_type);
+ vars["tag_size"] = StrCat(tag_size);
+
+ format.AddMap(vars);
+
+ format(
+ "{\n"
+ " PROTOBUF_FIELD_OFFSET($classtype$, $name$_),\n"
+ " static_cast<$uint32$>($presence$),\n"
+ " $nwtype$, $pwtype$, $ptype$, $tag_size$\n"
+ "},\n");
+ }
+
+ return last_field_number;
+}
+
+size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ if (!table_driven_) {
+ return 0;
+ }
+
+ std::vector<const FieldDescriptor*> ordered_fields =
+ SortFieldsByNumber(descriptor_);
+
+ format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
+ int last_field_number = 1;
+ for (auto field : ordered_fields) {
+ Formatter::SaveState saver(&format);
+
+ GOOGLE_CHECK_GE(field->number(), last_field_number);
+ for (; last_field_number < field->number(); last_field_number++) {
+ format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
+ }
+
+ std::map<std::string, std::string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ format.AddMap(vars);
+
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ if (HasPreservingUnknownEnumSemantics(field)) {
+ format(
+ "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
+ "nullptr}},\n");
+ } else {
+ format(
+ "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
+ "$1$_IsValid}},\n",
+ ClassName(field->enum_type(), true));
+ }
+ last_field_number++;
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE: {
+ if (field->is_map()) {
+ format(
+ "{::$proto_ns$::internal::AuxiliaryParseTableField::map_"
+ "aux{&::$proto_ns$::internal::ParseMap<$1$>}},\n",
+ QualifiedClassName(field->message_type(), options_));
+ last_field_number++;
+ break;
+ }
+ format.Set("field_classname", ClassName(field->message_type(), false));
+ format.Set("default_instance", QualifiedDefaultInstanceName(
+ field->message_type(), options_));
+
+ format(
+ "{::$proto_ns$::internal::AuxiliaryParseTableField::message_aux{\n"
+ " &$default_instance$}},\n");
+ last_field_number++;
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_STRING: {
+ std::string default_val;
+ switch (EffectiveStringCType(field, options_)) {
+ case FieldOptions::STRING:
+ default_val = field->default_value_string().empty()
+ ? "&::" + variables_["proto_ns"] +
+ "::internal::fixed_address_empty_string"
+ : "&" +
+ QualifiedClassName(descriptor_, options_) +
+ "::" + MakeDefaultName(field);
+ break;
+ case FieldOptions::CORD:
+ case FieldOptions::STRING_PIECE:
+ default_val =
+ "\"" + CEscape(field->default_value_string()) + "\"";
+ break;
+ }
+ format(
+ "{::$proto_ns$::internal::AuxiliaryParseTableField::string_aux{\n"
+ " $1$,\n"
+ " \"$2$\"\n"
+ "}},\n",
+ default_val, field->full_name());
+ last_field_number++;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return last_field_number;
+}
+
+std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
+ } else {
+ format("~0u, // no _has_bits_\n");
+ }
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n");
+ if (descriptor_->extension_range_count() > 0) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n");
+ } else {
+ format("~0u, // no _extensions_\n");
+ }
+ if (descriptor_->real_oneof_decl_count() > 0) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_[0]),\n");
+ } else {
+ format("~0u, // no _oneof_case_\n");
+ }
+ if (num_weak_fields_ > 0) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _weak_field_map_),\n");
+ } else {
+ format("~0u, // no _weak_field_map_\n");
+ }
+ if (!inlined_string_indices_.empty()) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, _inlined_string_donated_),\n");
+ } else {
+ format("~0u, // no _inlined_string_donated_\n");
+ }
+ const int kNumGenericOffsets = 6; // the number of fixed offsets above
+ const size_t offsets = kNumGenericOffsets + descriptor_->field_count() +
+ descriptor_->real_oneof_decl_count();
+ size_t entries = offsets;
+ for (auto field : FieldRange(descriptor_)) {
+ if (IsFieldStripped(field, options_)) {
+ format("~0u, // stripped\n");
+ continue;
+ }
+ // TODO(sbenza): We should not have an entry in the offset table for fields
+ // that do not use them.
+ if (field->options().weak() || field->real_containing_oneof()) {
+ // Mark the field to prevent unintentional access through reflection.
+ // Don't use the top bit because that is for unused fields.
+ format("::$proto_ns$::internal::kInvalidFieldOffsetTag");
+ } else {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field));
+ }
+
+ // Some information about a field is in the pdproto profile. The profile is
+ // only available at compile time. So we embed such information in the
+ // offset of the field, so that the information is available when
+ // reflectively accessing the field at run time.
+ //
+ // Embed whether the field is used to the MSB of the offset.
+ if (!IsFieldUsed(field, options_)) {
+ format(" | 0x80000000u // unused\n");
+ }
+
+ // Embed whether the field is eagerly verified lazy or inlined string to the
+ // LSB of the offset.
+ if (IsEagerlyVerifiedLazy(field, options_, scc_analyzer_)) {
+ format(" | 0x1u // eagerly verified lazy\n");
+ } else if (IsStringInlined(field, options_)) {
+ format(" | 0x1u // inlined\n");
+ }
+ format(",\n");
+ }
+
+ int count = 0;
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name());
+ count++;
+ }
+ GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count());
+
+ if (IsMapEntryMessage(descriptor_)) {
+ entries += 2;
+ format(
+ "0,\n"
+ "1,\n");
+ } else if (!has_bit_indices_.empty()) {
+ entries += has_bit_indices_.size();
+ for (int i = 0; i < has_bit_indices_.size(); i++) {
+ const std::string index =
+ has_bit_indices_[i] >= 0 ? StrCat(has_bit_indices_[i]) : "~0u";
+ format("$1$,\n", index);
+ }
+ }
+ if (!inlined_string_indices_.empty()) {
+ entries += inlined_string_indices_.size();
+ for (int inlined_string_indice : inlined_string_indices_) {
+ const std::string index = inlined_string_indice >= 0
+ ? StrCat(inlined_string_indice)
+ : "~0u";
+ format("$1$,\n", index);
+ }
+ }
+
+ return std::make_pair(entries, offsets);
+}
+
+void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ format("inline void $classname$::SharedCtor() {\n");
+
+ std::vector<bool> processed(optimized_order_.size(), false);
+ GenerateConstructorBody(printer, processed, false);
+
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("clear_has_$1$();\n", oneof->name());
+ }
+
+ format("}\n\n");
+}
+
+void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ format("inline void $classname$::SharedDtor() {\n");
+ format.Indent();
+ format("$DCHK$(GetArenaForAllocation() == nullptr);\n");
+ // Write the destructors for each field except oneof members.
+ // optimized_order_ does not contain oneof fields.
+ for (auto field : optimized_order_) {
+ field_generators_.get(field).GenerateDestructorCode(printer);
+ }
+
+ // Generate code to destruct oneofs. Clearing should do the work.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format(
+ "if (has_$1$()) {\n"
+ " clear_$1$();\n"
+ "}\n",
+ oneof->name());
+ }
+
+ if (num_weak_fields_) {
+ format("_weak_field_map_.ClearAll();\n");
+ }
+ format.Outdent();
+ format(
+ "}\n"
+ "\n");
+}
+
+void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ // Generate the ArenaDtor() method. Track whether any fields actually produced
+ // code that needs to be called.
+ format("void $classname$::ArenaDtor(void* object) {\n");
+ format.Indent();
+
+ // This code is placed inside a static method, rather than an ordinary one,
+ // since that simplifies Arena's destructor list (ordinary function pointers
+ // rather than member function pointers). _this is the object being
+ // destructed.
+ format(
+ "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
+ // avoid an "unused variable" warning in case no fields have dtor code.
+ "(void)_this;\n");
+
+ bool need_registration = false;
+ // Process non-oneof fields first.
+ for (auto field : optimized_order_) {
+ if (field_generators_.get(field).GenerateArenaDestructorCode(printer)) {
+ need_registration = true;
+ }
+ }
+
+ // Process oneof fields.
+ //
+ // Note: As of 10/5/2016, GenerateArenaDestructorCode does not emit anything
+ // and returns false for oneof fields.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ for (auto field : FieldRange(oneof)) {
+ if (!IsFieldStripped(field, options_) &&
+ field_generators_.get(field).GenerateArenaDestructorCode(printer)) {
+ need_registration = true;
+ }
+ }
+ }
+
+ format.Outdent();
+ format("}\n");
+
+ if (need_registration) {
+ format(
+ "inline void $classname$::RegisterArenaDtor(::$proto_ns$::Arena* "
+ "arena) {\n"
+ " if (arena != nullptr) {\n"
+ " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
+ " }\n"
+ "}\n");
+ } else {
+ format(
+ "void $classname$::RegisterArenaDtor(::$proto_ns$::Arena*) {\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ format(
+ "constexpr $classname$::$classname$(\n"
+ " ::$proto_ns$::internal::ConstantInitialized)");
+ format.Indent();
+ const char* field_sep = ":";
+ const auto put_sep = [&] {
+ format("\n$1$ ", field_sep);
+ field_sep = ",";
+ };
+
+ if (!IsMapEntryMessage(descriptor_)) {
+ // Process non-oneof fields first.
+ for (auto field : optimized_order_) {
+ auto& gen = field_generators_.get(field);
+ put_sep();
+ gen.GenerateConstinitInitializer(printer);
+ }
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ put_sep();
+ format("_any_metadata_(&type_url_, &value_)");
+ }
+
+ if (descriptor_->real_oneof_decl_count() != 0) {
+ put_sep();
+ format("_oneof_case_{}");
+ }
+ }
+
+ format.Outdent();
+ format("{}\n");
+}
+
+void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
+ std::vector<bool> processed,
+ bool copy_constructor) const {
+ Formatter format(printer, variables_);
+
+ const RunMap runs = FindRuns(
+ optimized_order_, [copy_constructor, this](const FieldDescriptor* field) {
+ return (copy_constructor && IsPOD(field)) ||
+ (!copy_constructor &&
+ CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_));
+ });
+
+ std::string pod_template;
+ if (copy_constructor) {
+ pod_template =
+ "::memcpy(&$first$_, &from.$first$_,\n"
+ " static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
+ " reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
+ } else {
+ pod_template =
+ "::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(\n"
+ " reinterpret_cast<char*>(&$first$_) - "
+ "reinterpret_cast<char*>(this)),\n"
+ " 0, static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
+ " reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
+ }
+
+ for (int i = 0; i < optimized_order_.size(); ++i) {
+ if (processed[i]) {
+ continue;
+ }
+
+ const FieldDescriptor* field = optimized_order_[i];
+ const auto it = runs.find(field);
+
+ // We only apply the memset technique to runs of more than one field, as
+ // assignment is better than memset for generated code clarity.
+ if (it != runs.end() && it->second > 1) {
+ // Use a memset, then skip run_length fields.
+ const size_t run_length = it->second;
+ const std::string first_field_name = FieldName(field);
+ const std::string last_field_name =
+ FieldName(optimized_order_[i + run_length - 1]);
+
+ format.Set("first", first_field_name);
+ format.Set("last", last_field_name);
+
+ format(pod_template.c_str());
+
+ i += run_length - 1;
+ // ++i at the top of the loop.
+ } else {
+ if (copy_constructor) {
+ field_generators_.get(field).GenerateCopyConstructorCode(printer);
+ } else {
+ field_generators_.get(field).GenerateConstructorCode(printer);
+ }
+ }
+ }
+}
+
+void MessageGenerator::GenerateStructors(io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ std::string superclass;
+ superclass = SuperClassName(descriptor_, options_);
+ std::string initializer_with_arena = superclass + "(arena, is_message_owned)";
+
+ if (descriptor_->extension_range_count() > 0) {
+ initializer_with_arena += ",\n _extensions_(arena)";
+ }
+
+ // Initialize member variables with arena constructor.
+ for (auto field : optimized_order_) {
+ GOOGLE_DCHECK(!IsFieldStripped(field, options_));
+ bool has_arena_constructor = field->is_repeated();
+ if (!field->real_containing_oneof() &&
+ (IsLazy(field, options_, scc_analyzer_) ||
+ IsStringPiece(field, options_) ||
+ (IsString(field, options_) && IsStringInlined(field, options_)))) {
+ has_arena_constructor = true;
+ }
+ if (has_arena_constructor) {
+ initializer_with_arena +=
+ std::string(",\n ") + FieldName(field) + std::string("_(arena)");
+ }
+ }
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)";
+ }
+ if (num_weak_fields_ > 0) {
+ initializer_with_arena += ", _weak_field_map_(arena)";
+ }
+
+ std::string initializer_null = superclass + "()";
+ if (IsAnyMessage(descriptor_, options_)) {
+ initializer_null += ", _any_metadata_(&type_url_, &value_)";
+ }
+ if (num_weak_fields_ > 0) {
+ initializer_null += ", _weak_field_map_(nullptr)";
+ }
+
+ format(
+ "$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
+ " bool is_message_owned)\n"
+ " : $1$ {\n",
+ initializer_with_arena);
+
+ if (!inlined_string_indices_.empty()) {
+ // Donate inline string fields.
+ format(" if (arena != nullptr) {\n");
+ for (size_t i = 0; i < InlinedStringDonatedSize(); ++i) {
+ format(" _inlined_string_donated_[$1$] = ~0u;\n", i);
+ }
+ format(" }\n");
+ }
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ " SharedCtor();\n"
+ " if (!is_message_owned) {\n"
+ " RegisterArenaDtor(arena);\n"
+ " }\n");
+ }
+ format(
+ " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
+ "}\n");
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+
+ // Generate the copy constructor.
+ if (UsingImplicitWeakFields(descriptor_->file(), options_)) {
+ // If we are in lite mode and using implicit weak fields, we generate a
+ // one-liner copy constructor that delegates to MergeFrom. This saves some
+ // code size and also cuts down on the complexity of implicit weak fields.
+ // We might eventually want to do this for all lite protos.
+ format(
+ "$classname$::$classname$(const $classname$& from)\n"
+ " : $classname$() {\n"
+ " MergeFrom(from);\n"
+ "}\n");
+ } else {
+ format(
+ "$classname$::$classname$(const $classname$& from)\n"
+ " : $superclass$()");
+ format.Indent();
+ format.Indent();
+ format.Indent();
+
+ // Do not copy inlined_string_donated_, because this is not an arena
+ // constructor.
+
+ if (!has_bit_indices_.empty()) {
+ format(",\n_has_bits_(from._has_bits_)");
+ }
+
+ std::vector<bool> processed(optimized_order_.size(), false);
+ for (int i = 0; i < optimized_order_.size(); i++) {
+ auto field = optimized_order_[i];
+ if (!(field->is_repeated() && !(field->is_map())) &&
+ !IsCord(field, options_)) {
+ continue;
+ }
+
+ processed[i] = true;
+ format(",\n$1$_(from.$1$_)", FieldName(field));
+ }
+
+ if (IsAnyMessage(descriptor_, options_)) {
+ format(",\n_any_metadata_(&type_url_, &value_)");
+ }
+ if (num_weak_fields_ > 0) {
+ format(",\n_weak_field_map_(from._weak_field_map_)");
+ }
+
+ format.Outdent();
+ format.Outdent();
+ format(" {\n");
+
+ format(
+ "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
+ "metadata_);\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ format(
+ "_extensions_.MergeFrom(internal_default_instance(), "
+ "from._extensions_);\n");
+ }
+
+ GenerateConstructorBody(printer, processed, true);
+
+ // Copy oneof fields. Oneof field requires oneof case check.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format(
+ "clear_has_$1$();\n"
+ "switch (from.$1$_case()) {\n",
+ oneof->name());
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateMergingCode(printer);
+ }
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format(
+ "case $1$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ ToUpper(oneof->name()));
+ format.Outdent();
+ format("}\n");
+ }
+
+ format.Outdent();
+ format(
+ " // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
+ "}\n"
+ "\n");
+ }
+
+ // Generate the shared constructor code.
+ GenerateSharedConstructorCode(printer);
+
+ // Generate the destructor.
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ format(
+ "$classname$::~$classname$() {\n"
+ " // @@protoc_insertion_point(destructor:$full_name$)\n"
+ " if (GetArenaForAllocation() != nullptr) return;\n"
+ " SharedDtor();\n"
+ " _internal_metadata_.Delete<$unknown_fields_type$>();\n"
+ "}\n"
+ "\n");
+ } else {
+ // For messages using simple base classes, having no destructor
+ // allows our vtable to share the same destructor as every other
+ // message with a simple base class. This works only as long as
+ // we have no fields needing destruction, of course. (No strings
+ // or extensions)
+ }
+
+ // Generate the shared destructor code.
+ GenerateSharedDestructorCode(printer);
+
+ // Generate the arena-specific destructor code.
+ GenerateArenaDestructorCode(printer);
+
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ // Generate SetCachedSize.
+ format(
+ "void $classname$::SetCachedSize(int size) const {\n"
+ " _cached_size_.Set(size);\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ format(
+ "template<> "
+ "PROTOBUF_NOINLINE "
+ "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n"
+ " return Arena::CreateMessageInternal< $classtype$ >(arena);\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateClear(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ // The maximum number of bytes we will memset to zero without checking their
+ // hasbit to see if a zero-init is necessary.
+ const int kMaxUnconditionalPrimitiveBytesClear = 4;
+
+ format(
+ "void $classname$::Clear() {\n"
+ "// @@protoc_insertion_point(message_clear_start:$full_name$)\n");
+ format.Indent();
+
+ format(
+ // TODO(jwb): It would be better to avoid emitting this if it is not used,
+ // rather than emitting a workaround for the resulting warning.
+ "$uint32$ cached_has_bits = 0;\n"
+ "// Prevent compiler warnings about cached_has_bits being unused\n"
+ "(void) cached_has_bits;\n\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ format("_extensions_.Clear();\n");
+ }
+
+ // Collect fields into chunks. Each chunk may have an if() condition that
+ // checks all hasbits in the chunk and skips it if none are set.
+ int zero_init_bytes = 0;
+ for (const auto& field : optimized_order_) {
+ if (CanInitializeByZeroing(field)) {
+ zero_init_bytes += EstimateAlignmentSize(field);
+ }
+ }
+ bool merge_zero_init = zero_init_bytes > kMaxUnconditionalPrimitiveBytesClear;
+ int chunk_count = 0;
+
+ std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
+ optimized_order_,
+ [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
+ chunk_count++;
+ // This predicate guarantees that there is only a single zero-init
+ // (memset) per chunk, and if present it will be at the beginning.
+ bool same = HasByteIndex(a) == HasByteIndex(b) &&
+ a->is_repeated() == b->is_repeated() &&
+ (CanInitializeByZeroing(a) == CanInitializeByZeroing(b) ||
+ (CanInitializeByZeroing(a) &&
+ (chunk_count == 1 || merge_zero_init)));
+ if (!same) chunk_count = 0;
+ return same;
+ });
+
+ ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+ int cached_has_word_index = -1;
+
+ for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+ std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
+ cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
+
+ const FieldDescriptor* memset_start = nullptr;
+ const FieldDescriptor* memset_end = nullptr;
+ bool saw_non_zero_init = false;
+
+ for (const auto& field : chunk) {
+ if (CanInitializeByZeroing(field)) {
+ GOOGLE_CHECK(!saw_non_zero_init);
+ if (!memset_start) memset_start = field;
+ memset_end = field;
+ } else {
+ saw_non_zero_init = true;
+ }
+ }
+
+ // Whether we wrap this chunk in:
+ // if (cached_has_bits & <chunk hasbits) { /* chunk. */ }
+ // We can omit the if() for chunk size 1, or if our fields do not have
+ // hasbits. I don't understand the rationale for the last part of the
+ // condition, but it matches the old logic.
+ const bool have_outer_if = HasBitIndex(chunk.front()) != kNoHasbit &&
+ chunk.size() > 1 &&
+ (memset_end != chunk.back() || merge_zero_init);
+
+ if (have_outer_if) {
+ // Emit an if() that will let us skip the whole chunk if none are set.
+ uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+ std::string chunk_mask_str =
+ StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+
+ // Check (up to) 8 has_bits at a time if we have more than one field in
+ // this chunk. Due to field layout ordering, we may check
+ // _has_bits_[last_chunk * 8 / 32] multiple times.
+ GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
+ GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
+
+ if (cached_has_word_index != HasWordIndex(chunk.front())) {
+ cached_has_word_index = HasWordIndex(chunk.front());
+ format("cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index);
+ }
+ format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
+ format.Indent();
+ }
+
+ if (memset_start) {
+ if (memset_start == memset_end) {
+ // For clarity, do not memset a single field.
+ field_generators_.get(memset_start)
+ .GenerateMessageClearingCode(printer);
+ } else {
+ format(
+ "::memset(&$1$_, 0, static_cast<size_t>(\n"
+ " reinterpret_cast<char*>(&$2$_) -\n"
+ " reinterpret_cast<char*>(&$1$_)) + sizeof($2$_));\n",
+ FieldName(memset_start), FieldName(memset_end));
+ }
+ }
+
+ // Clear all non-zero-initializable fields in the chunk.
+ for (const auto& field : chunk) {
+ if (CanInitializeByZeroing(field)) continue;
+ // It's faster to just overwrite primitive types, but we should only
+ // clear strings and messages if they were set.
+ //
+ // TODO(kenton): Let the CppFieldGenerator decide this somehow.
+ bool have_enclosing_if =
+ HasBitIndex(field) != kNoHasbit &&
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+
+ if (have_enclosing_if) {
+ PrintPresenceCheck(format, field, has_bit_indices_, printer,
+ &cached_has_word_index);
+ }
+
+ field_generators_.get(field).GenerateMessageClearingCode(printer);
+
+ if (have_enclosing_if) {
+ format.Outdent();
+ format("}\n");
+ }
+ }
+
+ if (have_outer_if) {
+ format.Outdent();
+ format("}\n");
+ }
+
+ if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+ // Reset here as it may have been updated in just closed if statement.
+ cached_has_word_index = -1;
+ }
+ }
+
+ // Step 4: Unions.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("clear_$1$();\n", oneof->name());
+ }
+
+ if (num_weak_fields_) {
+ format("_weak_field_map_.ClearAll();\n");
+ }
+
+ // We don't clear donated status.
+
+ if (!has_bit_indices_.empty()) {
+ // Step 5: Everything else.
+ format("_has_bits_.Clear();\n");
+ }
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ format("_internal_metadata_.Clear<$unknown_fields_type$>();\n");
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateOneofClear(io::Printer* printer) {
+ // Generated function clears the active field and union case (e.g. foo_case_).
+ int i = 0;
+ for (auto oneof : OneOfRange(descriptor_)) {
+ Formatter format(printer, variables_);
+ format.Set("oneofname", oneof->name());
+
+ format(
+ "void $classname$::clear_$oneofname$() {\n"
+ "// @@protoc_insertion_point(one_of_clear_start:$full_name$)\n");
+ format.Indent();
+ format("switch ($oneofname$_case()) {\n");
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ // We clear only allocated objects in oneofs
+ if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) {
+ format("// No need to clear\n");
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ }
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format(
+ "case $1$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ ToUpper(oneof->name()));
+ format.Outdent();
+ format(
+ "}\n"
+ "_oneof_case_[$1$] = $2$_NOT_SET;\n",
+ i, ToUpper(oneof->name()));
+ format.Outdent();
+ format(
+ "}\n"
+ "\n");
+ i++;
+ }
+}
+
+void MessageGenerator::GenerateSwap(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ format("void $classname$::InternalSwap($classname$* other) {\n");
+ format.Indent();
+ format("using std::swap;\n");
+
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ if (descriptor_->extension_range_count() > 0) {
+ format("_extensions_.InternalSwap(&other->_extensions_);\n");
+ }
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ if (HasSingularString(descriptor_, options_)) {
+ format(
+ "auto* lhs_arena = GetArenaForAllocation();\n"
+ "auto* rhs_arena = other->GetArenaForAllocation();\n");
+ }
+ format("_internal_metadata_.InternalSwap(&other->_internal_metadata_);\n");
+
+ if (!has_bit_indices_.empty()) {
+ for (int i = 0; i < HasBitsSize(); ++i) {
+ format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
+ }
+ }
+
+ // If possible, we swap several fields at once, including padding.
+ const RunMap runs =
+ FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
+ return CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_);
+ });
+
+ for (int i = 0; i < optimized_order_.size(); ++i) {
+ const FieldDescriptor* field = optimized_order_[i];
+ const auto it = runs.find(field);
+
+ // We only apply the memswap technique to runs of more than one field, as
+ // `swap(field_, other.field_)` is better than
+ // `memswap<...>(&field_, &other.field_)` for generated code readability.
+ if (it != runs.end() && it->second > 1) {
+ // Use a memswap, then skip run_length fields.
+ const size_t run_length = it->second;
+ const std::string first_field_name = FieldName(field);
+ const std::string last_field_name =
+ FieldName(optimized_order_[i + run_length - 1]);
+
+ format.Set("first", first_field_name);
+ format.Set("last", last_field_name);
+
+ format(
+ "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n"
+ " PROTOBUF_FIELD_OFFSET($classname$, $last$_)\n"
+ " + sizeof($classname$::$last$_)\n"
+ " - PROTOBUF_FIELD_OFFSET($classname$, $first$_)>(\n"
+ " reinterpret_cast<char*>(&$first$_),\n"
+ " reinterpret_cast<char*>(&other->$first$_));\n");
+
+ i += run_length - 1;
+ // ++i at the top of the loop.
+ } else {
+ field_generators_.get(field).GenerateSwappingCode(printer);
+ }
+ }
+
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("swap($1$_, other->$1$_);\n", oneof->name());
+ }
+
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ format("swap(_oneof_case_[$1$], other->_oneof_case_[$1$]);\n", i);
+ }
+
+ if (num_weak_fields_) {
+ format("_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n");
+ }
+ } else {
+ format("GetReflection()->Swap(this, other);");
+ }
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (!HasSimpleBaseClass(descriptor_, options_)) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ // We don't override the generalized MergeFrom (aka that which
+ // takes in the Message base class as a parameter); instead we just
+ // let the base Message::MergeFrom take care of it. The base MergeFrom
+ // knows how to quickly confirm the types exactly match, and if so, will
+ // use GetClassData() to retrieve the address of MergeImpl, which calls
+ // the fast MergeFrom overload. Most callers avoid all this by passing
+ // a "from" message that is the same type as the message being merged
+ // into, rather than a generic Message.
+
+ format(
+ "const ::$proto_ns$::Message::ClassData "
+ "$classname$::_class_data_ = {\n"
+ " ::$proto_ns$::Message::CopyWithSizeCheck,\n"
+ " $classname$::MergeImpl\n"
+ "};\n"
+ "const ::$proto_ns$::Message::ClassData*"
+ "$classname$::GetClassData() const { return &_class_data_; }\n"
+ "\n"
+ "void $classname$::MergeImpl(::$proto_ns$::Message* to,\n"
+ " const ::$proto_ns$::Message& from) {\n"
+ " static_cast<$classname$ *>(to)->MergeFrom(\n"
+ " static_cast<const $classname$ &>(from));\n"
+ "}\n"
+ "\n");
+ } else {
+ // Generate CheckTypeAndMergeFrom().
+ format(
+ "void $classname$::CheckTypeAndMergeFrom(\n"
+ " const ::$proto_ns$::MessageLite& from) {\n"
+ " MergeFrom(*::$proto_ns$::internal::DownCast<const $classname$*>(\n"
+ " &from));\n"
+ "}\n");
+ }
+ } else {
+ // In the simple case, we just define ClassData that vectors back to the
+ // simple implementation of Copy and Merge.
+ format(
+ "const ::$proto_ns$::Message::ClassData "
+ "$classname$::_class_data_ = {\n"
+ " $superclass$::CopyImpl,\n"
+ " $superclass$::MergeImpl,\n"
+ "};\n"
+ "const ::$proto_ns$::Message::ClassData*"
+ "$classname$::GetClassData() const { return &_class_data_; }\n"
+ "\n"
+ "\n");
+ }
+}
+
+void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
+ Formatter format(printer, variables_);
+ format(
+ "void $classname$::MergeFrom(const $classname$& from) {\n"
+ "$annotate_mergefrom$"
+ "// @@protoc_insertion_point(class_specific_merge_from_start:"
+ "$full_name$)\n"
+ " $DCHK$_NE(&from, this);\n");
+ format.Indent();
+
+ format(
+ "$uint32$ cached_has_bits = 0;\n"
+ "(void) cached_has_bits;\n\n");
+
+ std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
+ optimized_order_,
+ [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
+ return HasByteIndex(a) == HasByteIndex(b);
+ });
+
+ ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+
+ // cached_has_word_index maintains that:
+ // cached_has_bits = from._has_bits_[cached_has_word_index]
+ // for cached_has_word_index >= 0
+ int cached_has_word_index = -1;
+
+ for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+ const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
+ bool have_outer_if =
+ chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit;
+ cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.",
+ printer);
+
+ if (have_outer_if) {
+ // Emit an if() that will let us skip the whole chunk if none are set.
+ uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+ std::string chunk_mask_str =
+ StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+
+ // Check (up to) 8 has_bits at a time if we have more than one field in
+ // this chunk. Due to field layout ordering, we may check
+ // _has_bits_[last_chunk * 8 / 32] multiple times.
+ GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
+ GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
+
+ if (cached_has_word_index != HasWordIndex(chunk.front())) {
+ cached_has_word_index = HasWordIndex(chunk.front());
+ format("cached_has_bits = from._has_bits_[$1$];\n",
+ cached_has_word_index);
+ }
+
+ format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
+ format.Indent();
+ }
+
+ // Go back and emit merging code for each of the fields we processed.
+ bool deferred_has_bit_changes = false;
+ for (const auto field : chunk) {
+ const FieldGenerator& generator = field_generators_.get(field);
+
+ if (field->is_repeated()) {
+ generator.GenerateMergingCode(printer);
+ } else if (field->is_optional() && !HasHasbit(field)) {
+ // Merge semantics without true field presence: primitive fields are
+ // merged only if non-zero (numeric) or non-empty (string).
+ bool have_enclosing_if =
+ EmitFieldNonDefaultCondition(printer, "from.", field);
+ generator.GenerateMergingCode(printer);
+ if (have_enclosing_if) {
+ format.Outdent();
+ format("}\n");
+ }
+ } else if (field->options().weak() ||
+ cached_has_word_index != HasWordIndex(field)) {
+ // Check hasbit, not using cached bits.
+ GOOGLE_CHECK(HasHasbit(field));
+ format("if (from._internal_has_$1$()) {\n", FieldName(field));
+ format.Indent();
+ generator.GenerateMergingCode(printer);
+ format.Outdent();
+ format("}\n");
+ } else {
+ // Check hasbit, using cached bits.
+ GOOGLE_CHECK(HasHasbit(field));
+ int has_bit_index = has_bit_indices_[field->index()];
+ const std::string mask = StrCat(
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+ format("if (cached_has_bits & 0x$1$u) {\n", mask);
+ format.Indent();
+
+ if (have_outer_if && IsPOD(field)) {
+ // Defer hasbit modification until the end of chunk.
+ // This can reduce the number of loads/stores by up to 7 per 8 fields.
+ deferred_has_bit_changes = true;
+ generator.GenerateCopyConstructorCode(printer);
+ } else {
+ generator.GenerateMergingCode(printer);
+ }
+
+ format.Outdent();
+ format("}\n");
+ }
+ }
+
+ if (have_outer_if) {
+ if (deferred_has_bit_changes) {
+ // Flush the has bits for the primitives we deferred.
+ GOOGLE_CHECK_LE(0, cached_has_word_index);
+ format("_has_bits_[$1$] |= cached_has_bits;\n", cached_has_word_index);
+ }
+
+ format.Outdent();
+ format("}\n");
+ }
+
+ if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+ // Reset here as it may have been updated in just closed if statement.
+ cached_has_word_index = -1;
+ }
+ }
+
+ // Merge oneof fields. Oneof field requires oneof case check.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("switch (from.$1$_case()) {\n", oneof->name());
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateMergingCode(printer);
+ }
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format(
+ "case $1$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ ToUpper(oneof->name()));
+ format.Outdent();
+ format("}\n");
+ }
+ if (num_weak_fields_) {
+ format("_weak_field_map_.MergeFrom(from._weak_field_map_);\n");
+ }
+
+ // Merging of extensions and unknown fields is done last, to maximize
+ // the opportunity for tail calls.
+ if (descriptor_->extension_range_count() > 0) {
+ format(
+ "_extensions_.MergeFrom(internal_default_instance(), "
+ "from._extensions_);\n");
+ }
+
+ format(
+ "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
+ "metadata_);\n");
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
+ // We don't override the generalized CopyFrom (aka that which
+ // takes in the Message base class as a parameter); instead we just
+ // let the base Message::CopyFrom take care of it. The base MergeFrom
+ // knows how to quickly confirm the types exactly match, and if so, will
+ // use GetClassData() to get the address of Message::CopyWithSizeCheck,
+ // which calls Clear() and then MergeFrom(), as well as making sure that
+ // clearing the destination message doesn't alter the size of the source,
+ // when in debug builds.
+ // Most callers avoid this by passing a "from" message that is the same
+ // type as the message being merged into, rather than a generic Message.
+ }
+
+ // Generate the class-specific CopyFrom.
+ format(
+ "void $classname$::CopyFrom(const $classname$& from) {\n"
+ "// @@protoc_insertion_point(class_specific_copy_from_start:"
+ "$full_name$)\n");
+ format.Indent();
+
+ format("if (&from == this) return;\n");
+
+ if (!options_.opensource_runtime) {
+ // This check is disabled in the opensource release because we're
+ // concerned that many users do not define NDEBUG in their release builds.
+ format(
+ "#ifndef NDEBUG\n"
+ "size_t from_size = from.ByteSizeLong();\n"
+ "#endif\n"
+ "Clear();\n"
+ "#ifndef NDEBUG\n"
+ "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
+ " << \"Source of CopyFrom changed when clearing target. Either \"\n"
+ " \"source is a nested message in target (not allowed), or \"\n"
+ " \"another thread is modifying the source.\";\n"
+ "#endif\n");
+ } else {
+ format("Clear();\n");
+ }
+ format("MergeFrom(from);\n");
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateVerify(io::Printer* printer) {
+}
+
+void MessageGenerator::GenerateSerializeOneofFields(
+ io::Printer* printer, const std::vector<const FieldDescriptor*>& fields) {
+ Formatter format(printer, variables_);
+ GOOGLE_CHECK(!fields.empty());
+ if (fields.size() == 1) {
+ GenerateSerializeOneField(printer, fields[0], -1);
+ return;
+ }
+ // We have multiple mutually exclusive choices. Emit a switch statement.
+ const OneofDescriptor* oneof = fields[0]->containing_oneof();
+ format("switch ($1$_case()) {\n", oneof->name());
+ format.Indent();
+ for (auto field : fields) {
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
+ printer);
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format.Outdent();
+ // Doing nothing is an option.
+ format(
+ " default: ;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field,
+ int cached_has_bits_index) {
+ Formatter format(printer, variables_);
+ if (!field->options().weak()) {
+ // For weakfields, PrintFieldComment is called during iteration.
+ PrintFieldComment(format, field);
+ }
+
+ bool have_enclosing_if = false;
+ if (field->options().weak()) {
+ } else if (HasHasbit(field)) {
+ // Attempt to use the state of cached_has_bits, if possible.
+ int has_bit_index = HasBitIndex(field);
+ if (cached_has_bits_index == has_bit_index / 32) {
+ const std::string mask =
+ StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+
+ format("if (cached_has_bits & 0x$1$u) {\n", mask);
+ } else {
+ format("if (_internal_has_$1$()) {\n", FieldName(field));
+ }
+
+ format.Indent();
+ have_enclosing_if = true;
+ } else if (field->is_optional() && !HasHasbit(field)) {
+ have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
+ }
+
+ field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(printer);
+
+ if (have_enclosing_if) {
+ format.Outdent();
+ format("}\n");
+ }
+ format("\n");
+}
+
+void MessageGenerator::GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range) {
+ std::map<std::string, std::string> vars = variables_;
+ vars["start"] = StrCat(range->start);
+ vars["end"] = StrCat(range->end);
+ Formatter format(printer, vars);
+ format("// Extension range [$start$, $end$)\n");
+ format(
+ "target = _extensions_._InternalSerialize(\n"
+ "internal_default_instance(), $start$, $end$, target, stream);\n\n");
+}
+
+void MessageGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+ if (descriptor_->options().message_set_wire_format()) {
+ // Special-case MessageSet.
+ format(
+ "$uint8$* $classname$::_InternalSerialize(\n"
+ " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
+ "const {\n"
+ "$annotate_serialize$"
+ " target = _extensions_."
+ "InternalSerializeMessageSetWithCachedSizesToArray(\n" //
+ "internal_default_instance(), target, stream);\n");
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ format(
+ " target = ::$proto_ns$::internal::"
+ "InternalSerializeUnknownMessageSetItemsToArray(\n"
+ " $unknown_fields$, target, stream);\n");
+ format(
+ " return target;\n"
+ "}\n");
+ return;
+ }
+
+ format(
+ "$uint8$* $classname$::_InternalSerialize(\n"
+ " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
+ "const {\n"
+ "$annotate_serialize$");
+ format.Indent();
+
+ format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
+
+ if (!ShouldSerializeInOrder(descriptor_, options_)) {
+ format.Outdent();
+ format("#ifdef NDEBUG\n");
+ format.Indent();
+ }
+
+ GenerateSerializeWithCachedSizesBody(printer);
+
+ if (!ShouldSerializeInOrder(descriptor_, options_)) {
+ format.Outdent();
+ format("#else // NDEBUG\n");
+ format.Indent();
+
+ GenerateSerializeWithCachedSizesBodyShuffled(printer);
+
+ format.Outdent();
+ format("#endif // !NDEBUG\n");
+ format.Indent();
+ }
+
+ format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n");
+
+ format.Outdent();
+ format(
+ " return target;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateSerializeWithCachedSizesBody(
+ io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+ // If there are multiple fields in a row from the same oneof then we
+ // coalesce them and emit a switch statement. This is more efficient
+ // because it lets the C++ compiler know this is a "at most one can happen"
+ // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++
+ // compiler's emitted code might check has_y() even when has_x() is true.
+ class LazySerializerEmitter {
+ public:
+ LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer)
+ : mg_(mg),
+ format_(printer),
+ eager_(IsProto3(mg->descriptor_->file())),
+ cached_has_bit_index_(kNoHasbit) {}
+
+ ~LazySerializerEmitter() { Flush(); }
+
+ // If conditions allow, try to accumulate a run of fields from the same
+ // oneof, and handle them at the next Flush().
+ void Emit(const FieldDescriptor* field) {
+ if (eager_ || MustFlush(field)) {
+ Flush();
+ }
+ if (!field->real_containing_oneof()) {
+ // TODO(ckennelly): Defer non-oneof fields similarly to oneof fields.
+
+ if (!field->options().weak() && !field->is_repeated() && !eager_) {
+ // We speculatively load the entire _has_bits_[index] contents, even
+ // if it is for only one field. Deferring non-oneof emitting would
+ // allow us to determine whether this is going to be useful.
+ int has_bit_index = mg_->has_bit_indices_[field->index()];
+ if (cached_has_bit_index_ != has_bit_index / 32) {
+ // Reload.
+ int new_index = has_bit_index / 32;
+
+ format_("cached_has_bits = _has_bits_[$1$];\n", new_index);
+
+ cached_has_bit_index_ = new_index;
+ }
+ }
+
+ mg_->GenerateSerializeOneField(format_.printer(), field,
+ cached_has_bit_index_);
+ } else {
+ v_.push_back(field);
+ }
+ }
+
+ void EmitIfNotNull(const FieldDescriptor* field) {
+ if (field != nullptr) {
+ Emit(field);
+ }
+ }
+
+ void Flush() {
+ if (!v_.empty()) {
+ mg_->GenerateSerializeOneofFields(format_.printer(), v_);
+ v_.clear();
+ }
+ }
+
+ private:
+ // If we have multiple fields in v_ then they all must be from the same
+ // oneof. Would adding field to v_ break that invariant?
+ bool MustFlush(const FieldDescriptor* field) {
+ return !v_.empty() &&
+ v_[0]->containing_oneof() != field->containing_oneof();
+ }
+
+ MessageGenerator* mg_;
+ Formatter format_;
+ const bool eager_;
+ std::vector<const FieldDescriptor*> v_;
+
+ // cached_has_bit_index_ maintains that:
+ // cached_has_bits = from._has_bits_[cached_has_bit_index_]
+ // for cached_has_bit_index_ >= 0
+ int cached_has_bit_index_;
+ };
+
+ class LazyExtensionRangeEmitter {
+ public:
+ LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer)
+ : mg_(mg), format_(printer) {}
+
+ void AddToRange(const Descriptor::ExtensionRange* range) {
+ if (!has_current_range_) {
+ current_combined_range_ = *range;
+ has_current_range_ = true;
+ } else {
+ current_combined_range_.start =
+ std::min(current_combined_range_.start, range->start);
+ current_combined_range_.end =
+ std::max(current_combined_range_.end, range->end);
+ }
+ }
+
+ void Flush() {
+ if (has_current_range_) {
+ mg_->GenerateSerializeOneExtensionRange(format_.printer(),
+ &current_combined_range_);
+ }
+ has_current_range_ = false;
+ }
+
+ private:
+ MessageGenerator* mg_;
+ Formatter format_;
+ bool has_current_range_ = false;
+ Descriptor::ExtensionRange current_combined_range_;
+ };
+
+ // We need to track the largest weak field, because weak fields are serialized
+ // differently than normal fields. The WeakFieldMap::FieldWriter will
+ // serialize all weak fields that are ordinally between the last serialized
+ // weak field and the current field. In order to guarantee that all weak
+ // fields are serialized, we need to make sure to emit the code to serialize
+ // the largest weak field present at some point.
+ class LargestWeakFieldHolder {
+ public:
+ const FieldDescriptor* Release() {
+ const FieldDescriptor* result = field_;
+ field_ = nullptr;
+ return result;
+ }
+ void ReplaceIfLarger(const FieldDescriptor* field) {
+ if (field_ == nullptr || field_->number() < field->number()) {
+ field_ = field;
+ }
+ }
+
+ private:
+ const FieldDescriptor* field_ = nullptr;
+ };
+
+ std::vector<const FieldDescriptor*> ordered_fields =
+ SortFieldsByNumber(descriptor_);
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeSorter());
+ if (num_weak_fields_) {
+ format(
+ "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
+ "_weak_field_map_);\n");
+ }
+
+ format(
+ "$uint32$ cached_has_bits = 0;\n"
+ "(void) cached_has_bits;\n\n");
+
+ // Merge the fields and the extension ranges, both sorted by field number.
+ {
+ LazySerializerEmitter e(this, printer);
+ LazyExtensionRangeEmitter re(this, printer);
+ LargestWeakFieldHolder largest_weak_field;
+ int i, j;
+ for (i = 0, j = 0;
+ i < ordered_fields.size() || j < sorted_extensions.size();) {
+ if ((j == sorted_extensions.size()) ||
+ (i < descriptor_->field_count() &&
+ ordered_fields[i]->number() < sorted_extensions[j]->start)) {
+ const FieldDescriptor* field = ordered_fields[i++];
+ if (IsFieldStripped(field, options_)) {
+ continue;
+ }
+ re.Flush();
+ if (field->options().weak()) {
+ largest_weak_field.ReplaceIfLarger(field);
+ PrintFieldComment(format, field);
+ } else {
+ e.EmitIfNotNull(largest_weak_field.Release());
+ e.Emit(field);
+ }
+ } else {
+ e.EmitIfNotNull(largest_weak_field.Release());
+ e.Flush();
+ re.AddToRange(sorted_extensions[j++]);
+ }
+ }
+ re.Flush();
+ e.EmitIfNotNull(largest_weak_field.Release());
+ }
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
+ format.Indent();
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+ format(
+ "target = "
+ "::$proto_ns$::internal::WireFormat::"
+ "InternalSerializeUnknownFieldsToArray(\n"
+ " $unknown_fields$, target, stream);\n");
+ } else {
+ format(
+ "target = stream->WriteRaw($unknown_fields$.data(),\n"
+ " static_cast<int>($unknown_fields$.size()), target);\n");
+ }
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
+ io::Printer* printer) {
+ Formatter format(printer, variables_);
+
+ std::vector<const FieldDescriptor*> ordered_fields =
+ SortFieldsByNumber(descriptor_);
+ ordered_fields.erase(
+ std::remove_if(ordered_fields.begin(), ordered_fields.end(),
+ [this](const FieldDescriptor* f) {
+ return !IsFieldUsed(f, options_);
+ }),
+ ordered_fields.end());
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeSorter());
+
+ int num_fields = ordered_fields.size() + sorted_extensions.size();
+ constexpr int kLargePrime = 1000003;
+ GOOGLE_CHECK_LT(num_fields, kLargePrime)
+ << "Prime offset must be greater than the number of fields to ensure "
+ "those are coprime.";
+
+ if (num_weak_fields_) {
+ format(
+ "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
+ "_weak_field_map_);\n");
+ }
+
+ format("for (int i = $1$; i >= 0; i-- ) {\n", num_fields - 1);
+
+ format.Indent();
+ format("switch(i) {\n");
+ format.Indent();
+
+ int index = 0;
+ for (const auto* f : ordered_fields) {
+ format("case $1$: {\n", index++);
+ format.Indent();
+
+ GenerateSerializeOneField(printer, f, -1);
+
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+
+ for (const auto* r : sorted_extensions) {
+ format("case $1$: {\n", index++);
+ format.Indent();
+
+ GenerateSerializeOneExtensionRange(printer, r);
+
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+
+ format(
+ "default: {\n"
+ " $DCHK$(false) << \"Unexpected index: \" << i;\n"
+ "}\n");
+ format.Outdent();
+ format("}\n");
+
+ format.Outdent();
+ format("}\n");
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
+ format.Indent();
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+ format(
+ "target = "
+ "::$proto_ns$::internal::WireFormat::"
+ "InternalSerializeUnknownFieldsToArray(\n"
+ " $unknown_fields$, target, stream);\n");
+ } else {
+ format(
+ "target = stream->WriteRaw($unknown_fields$.data(),\n"
+ " static_cast<int>($unknown_fields$.size()), target);\n");
+ }
+ format.Outdent();
+ format("}\n");
+}
+
+std::vector<uint32_t> MessageGenerator::RequiredFieldsBitMask() const {
+ const int array_size = HasBitsSize();
+ std::vector<uint32_t> masks(array_size, 0);
+
+ for (auto field : FieldRange(descriptor_)) {
+ if (!field->is_required()) {
+ continue;
+ }
+
+ const int has_bit_index = has_bit_indices_[field->index()];
+ masks[has_bit_index / 32] |= static_cast<uint32_t>(1)
+ << (has_bit_index % 32);
+ }
+ return masks;
+}
+
+void MessageGenerator::GenerateByteSize(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+
+ if (descriptor_->options().message_set_wire_format()) {
+ // Special-case MessageSet.
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+ format(
+ "size_t $classname$::ByteSizeLong() const {\n"
+ "$annotate_bytesize$"
+ "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
+ " size_t total_size = _extensions_.MessageSetByteSize();\n"
+ " if ($have_unknown_fields$) {\n"
+ " total_size += ::$proto_ns$::internal::\n"
+ " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
+ " }\n"
+ " int cached_size = "
+ "::$proto_ns$::internal::ToCachedSize(total_size);\n"
+ " SetCachedSize(cached_size);\n"
+ " return total_size;\n"
+ "}\n");
+ return;
+ }
+
+ if (num_required_fields_ > 1) {
+ // Emit a function (rarely used, we hope) that handles the required fields
+ // by checking for each one individually.
+ format(
+ "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
+ "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
+ "$full_name$)\n");
+ format.Indent();
+ format("size_t total_size = 0;\n");
+ for (auto field : optimized_order_) {
+ if (field->is_required()) {
+ format(
+ "\n"
+ "if (_internal_has_$1$()) {\n",
+ FieldName(field));
+ format.Indent();
+ PrintFieldComment(format, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ format.Outdent();
+ format("}\n");
+ }
+ }
+ format(
+ "\n"
+ "return total_size;\n");
+ format.Outdent();
+ format("}\n");
+ }
+
+ format(
+ "size_t $classname$::ByteSizeLong() const {\n"
+ "$annotate_bytesize$"
+ "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n");
+ format.Indent();
+ format(
+ "size_t total_size = 0;\n"
+ "\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ format(
+ "total_size += _extensions_.ByteSize();\n"
+ "\n");
+ }
+
+ std::map<std::string, std::string> vars;
+ SetUnknownFieldsVariable(descriptor_, options_, &vars);
+ format.AddMap(vars);
+
+ // Handle required fields (if any). We expect all of them to be
+ // present, so emit one conditional that checks for that. If they are all
+ // present then the fast path executes; otherwise the slow path executes.
+ if (num_required_fields_ > 1) {
+ // The fast path works if all required fields are present.
+ const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
+ format("if ($1$) { // All required fields are present.\n",
+ ConditionalToCheckBitmasks(masks_for_has_bits));
+ format.Indent();
+ // Oneof fields cannot be required, so optimized_order_ contains all of the
+ // fields that we need to potentially emit.
+ for (auto field : optimized_order_) {
+ if (!field->is_required()) continue;
+ PrintFieldComment(format, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ format("\n");
+ }
+ format.Outdent();
+ format(
+ "} else {\n" // the slow path
+ " total_size += RequiredFieldsByteSizeFallback();\n"
+ "}\n");
+ } else {
+ // num_required_fields_ <= 1: no need to be tricky
+ for (auto field : optimized_order_) {
+ if (!field->is_required()) continue;
+ PrintFieldComment(format, field);
+ format("if (_internal_has_$1$()) {\n", FieldName(field));
+ format.Indent();
+ field_generators_.get(field).GenerateByteSize(printer);
+ format.Outdent();
+ format("}\n");
+ }
+ }
+
+ std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
+ optimized_order_,
+ [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool {
+ return a->label() == b->label() && HasByteIndex(a) == HasByteIndex(b);
+ });
+
+ // Remove chunks with required fields.
+ chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired),
+ chunks.end());
+
+ ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio);
+ int cached_has_word_index = -1;
+
+ format(
+ "$uint32$ cached_has_bits = 0;\n"
+ "// Prevent compiler warnings about cached_has_bits being unused\n"
+ "(void) cached_has_bits;\n\n");
+
+ for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+ const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
+ const bool have_outer_if =
+ chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit;
+ cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
+
+ if (have_outer_if) {
+ // Emit an if() that will let us skip the whole chunk if none are set.
+ uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+ std::string chunk_mask_str =
+ StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+
+ // Check (up to) 8 has_bits at a time if we have more than one field in
+ // this chunk. Due to field layout ordering, we may check
+ // _has_bits_[last_chunk * 8 / 32] multiple times.
+ GOOGLE_DCHECK_LE(2, popcnt(chunk_mask));
+ GOOGLE_DCHECK_GE(8, popcnt(chunk_mask));
+
+ if (cached_has_word_index != HasWordIndex(chunk.front())) {
+ cached_has_word_index = HasWordIndex(chunk.front());
+ format("cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index);
+ }
+ format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
+ format.Indent();
+ }
+
+ // Go back and emit checks for each of the fields we processed.
+ for (int j = 0; j < chunk.size(); j++) {
+ const FieldDescriptor* field = chunk[j];
+ const FieldGenerator& generator = field_generators_.get(field);
+ bool have_enclosing_if = false;
+ bool need_extra_newline = false;
+
+ PrintFieldComment(format, field);
+
+ if (field->is_repeated()) {
+ // No presence check is required.
+ need_extra_newline = true;
+ } else if (HasHasbit(field)) {
+ PrintPresenceCheck(format, field, has_bit_indices_, printer,
+ &cached_has_word_index);
+ have_enclosing_if = true;
+ } else {
+ // Without field presence: field is serialized only if it has a
+ // non-default value.
+ have_enclosing_if =
+ EmitFieldNonDefaultCondition(printer, "this->", field);
+ }
+
+ generator.GenerateByteSize(printer);
+
+ if (have_enclosing_if) {
+ format.Outdent();
+ format(
+ "}\n"
+ "\n");
+ }
+ if (need_extra_newline) {
+ format("\n");
+ }
+ }
+
+ if (have_outer_if) {
+ format.Outdent();
+ format("}\n");
+ }
+
+ if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+ // Reset here as it may have been updated in just closed if statement.
+ cached_has_word_index = -1;
+ }
+ }
+
+ // Fields inside a oneof don't use _has_bits_ so we count them in a separate
+ // pass.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ format("switch ($1$_case()) {\n", oneof->name());
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ PrintFieldComment(format, field);
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateByteSize(printer);
+ }
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format(
+ "case $1$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ ToUpper(oneof->name()));
+ format.Outdent();
+ format("}\n");
+ }
+
+ if (num_weak_fields_) {
+ // TagSize + MessageSize
+ format("total_size += _weak_field_map_.ByteSizeLong();\n");
+ }
+
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+ // We go out of our way to put the computation of the uncommon path of
+ // unknown fields in tail position. This allows for better code generation
+ // of this function for simple protos.
+ format(
+ "return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);\n");
+ } else {
+ format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
+ format(" total_size += $unknown_fields$.size();\n");
+ format("}\n");
+
+ // We update _cached_size_ even though this is a const method. Because
+ // const methods might be called concurrently this needs to be atomic
+ // operations or the program is undefined. In practice, since any
+ // concurrent writes will be writing the exact same value, normal writes
+ // will work on all common processors. We use a dedicated wrapper class to
+ // abstract away the underlying atomic. This makes it easier on platforms
+ // where even relaxed memory order might have perf impact to replace it with
+ // ordinary loads and stores.
+ format(
+ "int cached_size = ::$proto_ns$::internal::ToCachedSize(total_size);\n"
+ "SetCachedSize(cached_size);\n"
+ "return total_size;\n");
+ }
+
+ format.Outdent();
+ format("}\n");
+}
+
+void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+ if (HasSimpleBaseClass(descriptor_, options_)) return;
+ Formatter format(printer, variables_);
+ format("bool $classname$::IsInitialized() const {\n");
+ format.Indent();
+
+ if (descriptor_->extension_range_count() > 0) {
+ format(
+ "if (!_extensions_.IsInitialized()) {\n"
+ " return false;\n"
+ "}\n\n");
+ }
+
+ if (num_required_fields_ > 0) {
+ format(
+ "if (_Internal::MissingRequiredFields(_has_bits_))"
+ " return false;\n");
+ }
+
+ // Now check that all non-oneof embedded messages are initialized.
+ for (auto field : optimized_order_) {
+ field_generators_.get(field).GenerateIsInitialized(printer);
+ }
+ if (num_weak_fields_) {
+ // For Weak fields.
+ format("if (!_weak_field_map_.IsInitialized()) return false;\n");
+ }
+ // Go through the oneof fields, emitting a switch if any might have required
+ // fields.
+ for (auto oneof : OneOfRange(descriptor_)) {
+ bool has_required_fields = false;
+ for (auto field : FieldRange(oneof)) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+ scc_analyzer_->HasRequiredFields(field->message_type())) {
+ has_required_fields = true;
+ break;
+ }
+ }
+
+ if (!has_required_fields) {
+ continue;
+ }
+
+ format("switch ($1$_case()) {\n", oneof->name());
+ format.Indent();
+ for (auto field : FieldRange(oneof)) {
+ format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
+ format.Indent();
+ if (!IsFieldStripped(field, options_)) {
+ field_generators_.get(field).GenerateIsInitialized(printer);
+ }
+ format("break;\n");
+ format.Outdent();
+ format("}\n");
+ }
+ format(
+ "case $1$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ ToUpper(oneof->name()));
+ format.Outdent();
+ format("}\n");
+ }
+
+ format.Outdent();
+ format(
+ " return true;\n"
+ "}\n");
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.h
new file mode 100644
index 00000000..592af570
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message.h
@@ -0,0 +1,231 @@
+// 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_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
+
+#include <cstdint>
+#include <memory>
+#include <set>
+#include <string>
+
+#include <compiler/cpp/cpp_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_message_layout_helper.h>
+#include <compiler/cpp/cpp_options.h>
+#include <compiler/cpp/cpp_parse_function_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class EnumGenerator; // enum.h
+class ExtensionGenerator; // extension.h
+
+class MessageGenerator {
+ public:
+ // See generator.cc for the meaning of dllexport_decl.
+ MessageGenerator(const Descriptor* descriptor,
+ const std::map<std::string, std::string>& vars,
+ int index_in_file_messages, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~MessageGenerator();
+
+ // Append the two types of nested generators to the corresponding vector.
+ void AddGenerators(
+ std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
+ std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
+
+ // 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);
+
+ // Source file stuff.
+
+ // Generate all non-inline methods for this class.
+ void GenerateClassMethods(io::Printer* printer);
+
+ // Generate source file code that should go outside any namespace.
+ void GenerateSourceInProto2Namespace(io::Printer* printer);
+
+ private:
+ // Generate declarations and definitions of accessors for fields.
+ void GenerateFieldAccessorDeclarations(io::Printer* printer);
+ void GenerateFieldAccessorDefinitions(io::Printer* printer);
+
+ // Generate the table-driven parsing array. Returns the number of entries
+ // generated.
+ size_t GenerateParseOffsets(io::Printer* printer);
+ size_t GenerateParseAuxTable(io::Printer* printer);
+ // Generates a ParseTable entry. Returns whether the proto uses
+ // table-driven parsing.
+ bool GenerateParseTable(io::Printer* printer, size_t offset,
+ size_t aux_offset);
+
+ // Generate the field offsets array. Returns the a pair of the total number
+ // 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);
+ // For each field generates a table entry describing the field for the
+ // table driven serializer.
+ int GenerateFieldMetadata(io::Printer* printer);
+
+ // Generate constructors and destructor.
+ void GenerateStructors(io::Printer* printer);
+
+ // The compiler typically generates multiple copies of each constructor and
+ // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
+ // Placing common code in a separate method reduces the generated code size.
+ //
+ // Generate the shared constructor code.
+ 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 the constexpr constructor for constant initialization of the
+ // default instance.
+ void GenerateConstexprConstructor(io::Printer* printer);
+
+ // Generate standard Message methods.
+ void GenerateClear(io::Printer* printer);
+ void GenerateOneofClear(io::Printer* printer);
+ void GenerateVerify(io::Printer* printer);
+ void GenerateSerializeWithCachedSizes(io::Printer* printer);
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
+ void GenerateSerializeWithCachedSizesBody(io::Printer* printer);
+ void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
+ void GenerateByteSize(io::Printer* printer);
+ void GenerateMergeFrom(io::Printer* printer);
+ void GenerateClassSpecificMergeFrom(io::Printer* printer);
+ void GenerateCopyFrom(io::Printer* printer);
+ void GenerateSwap(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
+
+ // Helpers for GenerateSerializeWithCachedSizes().
+ //
+ // cached_has_bit_index maintains that:
+ // cached_has_bits = _has_bits_[cached_has_bit_index]
+ // for cached_has_bit_index >= 0
+ void GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field,
+ int cached_has_bits_index);
+ // 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);
+ void GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ // Generates has_foo() functions and variables for singular field has-bits.
+ void GenerateSingularFieldHasBits(const FieldDescriptor* field,
+ Formatter format);
+ // Generates has_foo() functions and variables for oneof field has-bits.
+ void GenerateOneofHasBits(io::Printer* printer);
+ // Generates has_foo_bar() functions for oneof members.
+ void GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const Formatter& format);
+ // Generates the clear_foo() method for a field.
+ void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
+ Formatter format);
+
+ void GenerateConstructorBody(io::Printer* printer,
+ std::vector<bool> already_processed,
+ bool copy_constructor) const;
+
+ size_t HasBitsSize() const;
+ size_t InlinedStringDonatedSize() const;
+ int HasBitIndex(const FieldDescriptor* a) const;
+ int HasByteIndex(const FieldDescriptor* a) const;
+ int HasWordIndex(const FieldDescriptor* a) const;
+ bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
+ std::vector<uint32_t> RequiredFieldsBitMask() const;
+
+ const Descriptor* descriptor_;
+ int index_in_file_messages_;
+ std::string classname_;
+ Options options_;
+ FieldGeneratorMap field_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 and weak fields.
+ std::vector<const FieldDescriptor*> optimized_order_;
+ std::vector<int> has_bit_indices_;
+ int max_has_bit_index_;
+
+ // A map from field index to inlined_string index. For non-inlined-string
+ // fields, the element is -1.
+ std::vector<int> inlined_string_indices_;
+ // The count of inlined_string fields in the message.
+ int max_inlined_string_index_;
+
+ std::vector<const EnumGenerator*> enum_generators_;
+ std::vector<const ExtensionGenerator*> extension_generators_;
+ int num_required_fields_;
+ int num_weak_fields_;
+ // table_driven_ indicates the generated message uses table-driven parsing.
+ bool table_driven_;
+
+ std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
+ std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
+
+ MessageSCCAnalyzer* scc_analyzer_;
+
+ std::map<std::string, std::string> variables_;
+
+ friend class FileGenerator;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.cc
new file mode 100644
index 00000000..a0b80bd0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.cc
@@ -0,0 +1,892 @@
+// 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 <compiler/cpp/cpp_message_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <io/printer.h>
+
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+std::string ReinterpretCast(const std::string& type,
+ const std::string& expression,
+ bool implicit_weak_field) {
+ if (implicit_weak_field) {
+ return "reinterpret_cast< " + type + " >(" + expression + ")";
+ } else {
+ return expression;
+ }
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ const Options& options, bool implicit_weak,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, variables, options);
+ (*variables)["type"] = FieldMessageTypeName(descriptor, options);
+ (*variables)["casted_member"] = ReinterpretCast(
+ (*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
+ (*variables)["type_default_instance"] =
+ QualifiedDefaultInstanceName(descriptor->message_type(), options);
+ (*variables)["type_default_instance_ptr"] =
+ QualifiedDefaultInstancePtr(descriptor->message_type(), options);
+ (*variables)["type_reference_function"] =
+ implicit_weak ? (" ::" + (*variables)["proto_ns"] +
+ "::internal::StrongReference(reinterpret_cast<const " +
+ (*variables)["type"] + "&>(\n" +
+ (*variables)["type_default_instance"] + "));\n")
+ : "";
+ // 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();
+}
+
+} // namespace
+
+// ===================================================================
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : FieldGenerator(descriptor, options),
+ implicit_weak_field_(
+ IsImplicitWeakField(descriptor, options, scc_analyzer)),
+ has_required_fields_(
+ scc_analyzer->HasRequiredFields(descriptor->message_type())) {
+ SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format("::$proto_ns$::MessageLite* $name$_;\n");
+ } else {
+ format("$type$* $name$_;\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (IsFieldStripped(descriptor_, options_)) {
+ format(
+ "$deprecated_attr$const $type$& ${1$$name$$}$() const { "
+ "__builtin_trap(); }\n"
+ "PROTOBUF_NODISCARD $deprecated_attr$$type$* "
+ "${1$$release_name$$}$() { "
+ "__builtin_trap(); }\n"
+ "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { "
+ "__builtin_trap(); }\n"
+ "$deprecated_attr$void ${1$set_allocated_$name$$}$"
+ "($type$* $name$) { __builtin_trap(); }\n"
+ "$deprecated_attr$void "
+ "${1$unsafe_arena_set_allocated_$name$$}$(\n"
+ " $type$* $name$) { __builtin_trap(); }\n"
+ "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { "
+ "__builtin_trap(); }\n",
+ descriptor_);
+ return;
+ }
+ format(
+ "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
+ "PROTOBUF_NODISCARD $deprecated_attr$$type$* "
+ "${1$$release_name$$}$();\n"
+ "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
+ "$deprecated_attr$void ${1$set_allocated_$name$$}$"
+ "($type$* $name$);\n",
+ descriptor_);
+ if (!IsFieldStripped(descriptor_, options_)) {
+ format(
+ "private:\n"
+ "const $type$& ${1$_internal_$name$$}$() const;\n"
+ "$type$* ${1$_internal_mutable_$name$$}$();\n"
+ "public:\n",
+ descriptor_);
+ }
+ format(
+ "$deprecated_attr$void "
+ "${1$unsafe_arena_set_allocated_$name$$}$(\n"
+ " $type$* $name$);\n"
+ "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
+ descriptor_);
+}
+
+void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const {
+}
+
+void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline const $type$& $classname$::_internal_$name$() const {\n"
+ "$type_reference_function$"
+ " const $type$* p = $casted_member$;\n"
+ " return p != nullptr ? *p : reinterpret_cast<const $type$&>(\n"
+ " $type_default_instance$);\n"
+ "}\n"
+ "inline const $type$& $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n");
+
+ format(
+ "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$) {\n"
+ // If we're not on an arena, free whatever we were holding before.
+ // (If we are on arena, we can just forget the earlier pointer.)
+ " if (GetArenaForAllocation() == nullptr) {\n"
+ " delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n"
+ " }\n");
+ if (implicit_weak_field_) {
+ format(
+ " $name$_ = "
+ "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n");
+ } else {
+ format(" $name$_ = $name$;\n");
+ }
+ format(
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+ ":$full_name$)\n"
+ "}\n");
+ format(
+ "inline $type$* $classname$::$release_name$() {\n"
+ "$type_reference_function$"
+ "$annotate_release$"
+ " $clear_hasbit$\n"
+ " $type$* temp = $casted_member$;\n"
+ " $name$_ = nullptr;\n"
+ "#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+ " auto* old = reinterpret_cast<::$proto_ns$::MessageLite*>(temp);\n"
+ " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+ " if (GetArenaForAllocation() == nullptr) { delete old; }\n"
+ "#else // PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+ " if (GetArenaForAllocation() != nullptr) {\n"
+ " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+ " }\n"
+ "#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE\n"
+ " return temp;\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ "$annotate_release$"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
+ "$type_reference_function$"
+ " $clear_hasbit$\n"
+ " $type$* temp = $casted_member$;\n"
+ " $name$_ = nullptr;\n"
+ " return temp;\n"
+ "}\n");
+
+ format(
+ "inline $type$* $classname$::_internal_mutable_$name$() {\n"
+ "$type_reference_function$"
+ " $set_hasbit$\n"
+ " if ($name$_ == nullptr) {\n"
+ " auto* p = CreateMaybeMessage<$type$>(GetArenaForAllocation());\n");
+ if (implicit_weak_field_) {
+ format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
+ } else {
+ format(" $name$_ = p;\n");
+ }
+ format(
+ " }\n"
+ " return $casted_member$;\n"
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $type$* _msg = _internal_mutable_$name$();\n"
+ "$annotate_mutable$"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return _msg;\n"
+ "}\n");
+
+ // We handle the most common case inline, and delegate less common cases to
+ // the slow fallback function.
+ format(
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n");
+ format(" if (message_arena == nullptr) {\n");
+ if (IsCrossFileMessage(descriptor_)) {
+ format(
+ " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n");
+ } else {
+ format(" delete $name$_;\n");
+ }
+ format(
+ " }\n"
+ " if ($name$) {\n");
+ if (IsCrossFileMessage(descriptor_)) {
+ // We have to read the arena through the virtual method, because the type
+ // isn't defined in this file.
+ format(
+ " ::$proto_ns$::Arena* submessage_arena =\n"
+ " ::$proto_ns$::Arena::InternalHelper<\n"
+ " ::$proto_ns$::MessageLite>::GetOwningArena(\n"
+ " reinterpret_cast<::$proto_ns$::MessageLite*>("
+ "$name$));\n");
+ } else {
+ format(
+ " ::$proto_ns$::Arena* submessage_arena =\n"
+ " ::$proto_ns$::Arena::InternalHelper<$type$>::GetOwningArena("
+ "$name$);\n");
+ }
+ format(
+ " if (message_arena != submessage_arena) {\n"
+ " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
+ " message_arena, $name$, submessage_arena);\n"
+ " }\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n");
+ if (implicit_weak_field_) {
+ format(" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
+ } else {
+ format(" $name$_ = $name$;\n");
+ }
+ format(
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateInternalAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format(
+ "static const ::$proto_ns$::MessageLite& $name$("
+ "const $classname$* msg);\n"
+ "static ::$proto_ns$::MessageLite* mutable_$name$("
+ "$classname$* msg);\n");
+ } else {
+ format("static const $type$& $name$(const $classname$* msg);\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
+ io::Printer* printer) const {
+ // In theory, these accessors could be inline in _Internal. However, in
+ // practice, the linker is then not able to throw them out making implicit
+ // weak dependencies not work at all.
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ // These private accessors are used by MergeFrom and
+ // MergePartialFromCodedStream, and their purpose is to provide access to
+ // the field without creating a strong dependency on the message type.
+ format(
+ "const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n"
+ " const $classname$* msg) {\n"
+ " if (msg->$name$_ != nullptr) {\n"
+ " return *msg->$name$_;\n"
+ " } else if ($type_default_instance_ptr$ != nullptr) {\n"
+ " return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
+ " $type_default_instance_ptr$);\n"
+ " } else {\n"
+ " return "
+ "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
+ " }\n"
+ "}\n");
+ format(
+ "::$proto_ns$::MessageLite*\n"
+ "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
+ if (HasHasbit(descriptor_)) {
+ format(" msg->$set_hasbit$\n");
+ }
+ format(
+ " if (msg->$name$_ == nullptr) {\n"
+ " if ($type_default_instance_ptr$ == nullptr) {\n"
+ " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+ " ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
+ " msg->GetArenaForAllocation());\n"
+ " } else {\n"
+ " msg->$name$_ = \n"
+ " reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
+ " $type_default_instance_ptr$)->New(\n"
+ " msg->GetArenaForAllocation());\n"
+ " }\n"
+ " }\n"
+ " return msg->$name$_;\n"
+ "}\n");
+ } else {
+ // This inline accessor directly returns member field and is used in
+ // Serialize such that AFDO profile correctly captures access information to
+ // message fields under serialize.
+ format(
+ "const $type$&\n"
+ "$classname$::_Internal::$name$(const $classname$* msg) {\n"
+ " return *msg->$field_member$;\n"
+ "}\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (!HasHasbit(descriptor_)) {
+ // If we don't have has-bits, message presence is indicated only by ptr !=
+ // NULL. Thus on clear, we need to delete the object.
+ format(
+ "if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
+ " delete $name$_;\n"
+ "}\n"
+ "$name$_ = nullptr;\n");
+ } else {
+ format("if ($name$_ != nullptr) $name$_->Clear();\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateMessageClearingCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (!HasHasbit(descriptor_)) {
+ // If we don't have has-bits, message presence is indicated only by ptr !=
+ // NULL. Thus on clear, we need to delete the object.
+ format(
+ "if (GetArenaForAllocation() == nullptr && $name$_ != nullptr) {\n"
+ " delete $name$_;\n"
+ "}\n"
+ "$name$_ = nullptr;\n");
+ } else {
+ format(
+ "$DCHK$($name$_ != nullptr);\n"
+ "$name$_->Clear();\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format(
+ "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
+ " _Internal::$name$(&from));\n");
+ } else {
+ format(
+ "_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())"
+ ";\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format("swap($name$_, other->$name$_);\n");
+}
+
+void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (options_.opensource_runtime) {
+ // TODO(gerbens) Remove this when we don't need to destruct default
+ // instances. In google3 a default instance will never get deleted so we
+ // don't need to worry about that but in opensource protobuf default
+ // instances are deleted in shutdown process and we need to take special
+ // care when handling them.
+ format("if (this != internal_default_instance()) ");
+ }
+ format("delete $name$_;\n");
+}
+
+void MessageFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format("$name$_ = nullptr;\n");
+}
+
+void MessageFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format(
+ "if (from._internal_has_$name$()) {\n"
+ " $name$_ = new $type$(*from.$name$_);\n"
+ "} else {\n"
+ " $name$_ = nullptr;\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format(
+ "target = stream->EnsureSpace(target);\n"
+ "target = ::$proto_ns$::internal::WireFormatLite::\n"
+ " InternalWrite$declared_type$(\n"
+ " $number$, _Internal::$name$(this), target, stream);\n");
+}
+
+void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$ +\n"
+ " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
+ " *$field_member$);\n");
+}
+
+void MessageFieldGenerator::GenerateIsInitialized(io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ if (!has_required_fields_) return;
+
+ Formatter format(printer, variables_);
+ format(
+ "if (_internal_has_$name$()) {\n"
+ " if (!$name$_->IsInitialized()) return false;\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_(nullptr)");
+}
+
+// ===================================================================
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : MessageFieldGenerator(descriptor, options, scc_analyzer) {
+ SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " ::$proto_ns$::Arena* message_arena = GetArenaForAllocation();\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n");
+ if (descriptor_->file() != descriptor_->message_type()->file()) {
+ // We have to read the arena through the virtual method, because the type
+ // isn't defined in this file.
+ format(
+ " ::$proto_ns$::Arena* submessage_arena =\n"
+ " ::$proto_ns$::Arena::InternalHelper<\n"
+ " ::$proto_ns$::MessageLite>::GetOwningArena(\n"
+ " reinterpret_cast<::$proto_ns$::MessageLite*>("
+ "$name$));\n");
+ } else {
+ format(
+ " ::$proto_ns$::Arena* submessage_arena =\n"
+ " ::$proto_ns$::Arena::InternalHelper<"
+ "$type$>::GetOwningArena($name$);\n");
+ }
+ format(
+ " if (message_arena != submessage_arena) {\n"
+ " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
+ " message_arena, $name$, submessage_arena);\n"
+ " }\n"
+ " set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
+ " }\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$* $classname$::$release_name$() {\n"
+ "$annotate_release$"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
+ " if (_internal_has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $field_member$;\n"
+ " if (GetArenaForAllocation() != nullptr) {\n"
+ " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
+ " }\n"
+ " $field_member$ = nullptr;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return nullptr;\n"
+ " }\n"
+ "}\n");
+
+ format(
+ "inline const $type$& $classname$::_internal_$name$() const {\n"
+ " return _internal_has_$name$()\n"
+ " ? *$field_member$\n"
+ " : reinterpret_cast< $type$&>($type_default_instance$);\n"
+ "}\n"
+ "inline const $type$& $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ "$annotate_release$"
+ " // @@protoc_insertion_point(field_unsafe_arena_release"
+ ":$full_name$)\n"
+ " if (_internal_has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $field_member$;\n"
+ " $field_member$ = nullptr;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return nullptr;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$"
+ "($type$* $name$) {\n"
+ // We rely on the oneof clear method to free the earlier contents of
+ // this oneof. We can directly use the pointer we're given to set the
+ // new value.
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
+ " }\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+ "$full_name$)\n"
+ "}\n"
+ "inline $type$* $classname$::_internal_mutable_$name$() {\n"
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $field_member$ = CreateMaybeMessage< $type$ "
+ ">(GetArenaForAllocation());\n"
+ " }\n"
+ " return $field_member$;\n"
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $type$* _msg = _internal_mutable_$name$();\n"
+ "$annotate_mutable$"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return _msg;\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format(
+ "if (GetArenaForAllocation() == nullptr) {\n"
+ " delete $field_member$;\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::GenerateMessageClearingCode(
+ io::Printer* printer) const {
+ GenerateClearingCode(printer);
+}
+
+void MessageOneofFieldGenerator::GenerateSwappingCode(
+ io::Printer* printer) const {
+ // Don't print any swapping code. Swapping the union will swap this field.
+}
+
+void MessageOneofFieldGenerator::GenerateDestructorCode(
+ io::Printer* printer) const {
+ // We inherit from MessageFieldGenerator, so we need to override the default
+ // behavior.
+}
+
+void MessageOneofFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ // Don't print any constructor code. The field is in a union. We allocate
+ // space only when this field is used.
+}
+
+void MessageOneofFieldGenerator::GenerateIsInitialized(
+ io::Printer* printer) const {
+ if (!has_required_fields_) return;
+
+ Formatter format(printer, variables_);
+ format(
+ "if (_internal_has_$name$()) {\n"
+ " if (!$field_member$->IsInitialized()) return false;\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer)
+ : FieldGenerator(descriptor, options),
+ implicit_weak_field_(
+ IsImplicitWeakField(descriptor, options, scc_analyzer)),
+ has_required_fields_(
+ scc_analyzer->HasRequiredFields(descriptor->message_type())) {
+ SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n");
+ } else {
+ format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (IsFieldStripped(descriptor_, options_)) {
+ format(
+ "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { "
+ "__builtin_trap(); }\n"
+ "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
+ " ${1$mutable_$name$$}$() { __builtin_trap(); }\n"
+ "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { "
+ "__builtin_trap(); }\n"
+ "$deprecated_attr$$type$* ${1$add_$name$$}$() { "
+ "__builtin_trap(); }\n"
+ "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
+ " ${1$$name$$}$() const { __builtin_trap(); }\n",
+ descriptor_);
+ return;
+ }
+ format(
+ "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
+ "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
+ " ${1$mutable_$name$$}$();\n",
+ descriptor_);
+ if (!IsFieldStripped(descriptor_, options_)) {
+ format(
+ "private:\n"
+ "const $type$& ${1$_internal_$name$$}$(int index) const;\n"
+ "$type$* ${1$_internal_add_$name$$}$();\n"
+ "public:\n",
+ descriptor_);
+ }
+ format(
+ "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
+ "$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
+ "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
+ " ${1$$name$$}$() const;\n",
+ descriptor_);
+}
+
+void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format.Set("weak", implicit_weak_field_ ? ".weak" : "");
+
+ format(
+ "inline $type$* $classname$::mutable_$name$(int index) {\n"
+ "$annotate_mutable$"
+ // TODO(dlj): move insertion points
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ "$type_reference_function$"
+ " return $name$_$weak$.Mutable(index);\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ "$annotate_mutable_list$"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ "$type_reference_function$"
+ " return &$name$_$weak$;\n"
+ "}\n");
+
+ if (options_.safe_boundary_check) {
+ format(
+ "inline const $type$& $classname$::_internal_$name$(int index) const "
+ "{\n"
+ " return $name$_$weak$.InternalCheckedGet(index,\n"
+ " reinterpret_cast<const $type$&>($type_default_instance$));\n"
+ "}\n");
+ } else {
+ format(
+ "inline const $type$& $classname$::_internal_$name$(int index) const "
+ "{\n"
+ "$type_reference_function$"
+ " return $name$_$weak$.Get(index);\n"
+ "}\n");
+ }
+
+ format(
+ "inline const $type$& $classname$::$name$(int index) const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$(index);\n"
+ "}\n"
+ "inline $type$* $classname$::_internal_add_$name$() {\n"
+ " return $name$_$weak$.Add();\n"
+ "}\n"
+ "inline $type$* $classname$::add_$name$() {\n"
+ " $type$* _add = _internal_add_$name$();\n"
+ "$annotate_add_mutable$"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ " return _add;\n"
+ "}\n");
+
+ format(
+ "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ "$annotate_list$"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ "$type_reference_function$"
+ " return $name$_$weak$;\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format("$name$_.Clear();\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format("$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSwappingCode(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format("$name$_.InternalSwap(&other->$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ // Not needed for repeated fields.
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format(
+ "for (auto it = this->$name$_.pointer_begin(),\n"
+ " end = this->$name$_.pointer_end(); it < end; ++it) {\n"
+ " target = stream->EnsureSpace(target);\n"
+ " target = ::$proto_ns$::internal::WireFormatLite::\n"
+ " InternalWrite$declared_type$($number$, **it, target, stream);\n"
+ "}\n");
+ } else {
+ format(
+ "for (unsigned int i = 0,\n"
+ " n = static_cast<unsigned int>(this->_internal_$name$_size()); i < "
+ "n; i++) "
+ "{\n"
+ " target = stream->EnsureSpace(target);\n"
+ " target = ::$proto_ns$::internal::WireFormatLite::\n"
+ " InternalWrite$declared_type$($number$, "
+ "this->_internal_$name$(i), target, stream);\n"
+ "}\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::GenerateByteSize(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$UL * this->_internal_$name$_size();\n"
+ "for (const auto& msg : this->$name$_) {\n"
+ " total_size +=\n"
+ " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateIsInitialized(
+ io::Printer* printer) const {
+ GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
+
+ if (!has_required_fields_) return;
+
+ Formatter format(printer, variables_);
+ if (implicit_weak_field_) {
+ format(
+ "if (!::$proto_ns$::internal::AllAreInitializedWeak($name$_.weak))\n"
+ " return false;\n");
+ } else {
+ format(
+ "if (!::$proto_ns$::internal::AllAreInitialized($name$_))\n"
+ " return false;\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_()");
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.h
new file mode 100644
index 00000000..88744299
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_field.h
@@ -0,0 +1,144 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// 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 <compiler/cpp/cpp_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MessageFieldGenerator : public FieldGenerator {
+ public:
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~MessageFieldGenerator() override;
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const override;
+ void GenerateInternalAccessorDeclarations(
+ io::Printer* printer) const override;
+ void GenerateInternalAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMessageClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateDestructorCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateIsInitialized(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ protected:
+ const bool implicit_weak_field_;
+ const bool has_required_fields_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class MessageOneofFieldGenerator : public MessageFieldGenerator {
+ public:
+ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~MessageOneofFieldGenerator() override;
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+
+ // MessageFieldGenerator, from which we inherit, overrides this so we need to
+ // override it as well.
+ void GenerateMessageClearingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateDestructorCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateIsInitialized(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public FieldGenerator {
+ public:
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer);
+ ~RepeatedMessageFieldGenerator() override;
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override {}
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateIsInitialized(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ private:
+ const bool implicit_weak_field_;
+ const bool has_required_fields_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_layout_helper.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_layout_helper.h
new file mode 100644
index 00000000..aa088a2a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_message_layout_helper.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: seongkim@google.com (Seong Beom Kim)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
+
+#include <compiler/cpp/cpp_options.h>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class MessageSCCAnalyzer;
+
+// Provides an abstract interface to optimize message layout
+// by rearranging the fields of a message.
+class MessageLayoutHelper {
+ public:
+ virtual ~MessageLayoutHelper() {}
+
+ virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) = 0;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_move_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_move_unittest.cc
new file mode 100644
index 00000000..ccb83acf
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_move_unittest.cc
@@ -0,0 +1,169 @@
+// 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 <stubs/common.h>
+#include <test_util.h>
+#include <unittest.pb.h>
+#include <gtest/gtest.h>
+
+#if LANG_CXX11
+#include <type_traits>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+// Moves are enabled only when compiling with a C++11 compiler or newer.
+#if LANG_CXX11
+
+TEST(MovableMessageTest, MoveConstructor) {
+ protobuf_unittest::TestAllTypes message1;
+ TestUtil::SetAllFields(&message1);
+ const auto* nested = &message1.optional_nested_message();
+
+ protobuf_unittest::TestAllTypes message2(std::move(message1));
+ TestUtil::ExpectAllFieldsSet(message2);
+
+ // Check if the optional_nested_message was actually moved (and not just
+ // copied).
+ EXPECT_EQ(nested, &message2.optional_nested_message());
+ EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveAssignmentOperator) {
+ protobuf_unittest::TestAllTypes message1;
+ TestUtil::SetAllFields(&message1);
+ const auto* nested = &message1.optional_nested_message();
+
+ protobuf_unittest::TestAllTypes message2;
+ message2 = std::move(message1);
+ TestUtil::ExpectAllFieldsSet(message2);
+
+ // Check if the optional_nested_message was actually moved (and not just
+ // copied).
+ EXPECT_EQ(nested, &message2.optional_nested_message());
+ EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, SelfMoveAssignment) {
+ // The `self` reference is necessary to defeat -Wself-move.
+ protobuf_unittest::TestAllTypes message, &self = message;
+ TestUtil::SetAllFields(&message);
+ message = std::move(self);
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(MovableMessageTest, MoveSameArena) {
+ Arena arena;
+
+ auto* message1_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+ TestUtil::SetAllFields(message1_on_arena);
+ const auto* nested = &message1_on_arena->optional_nested_message();
+
+ auto* message2_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+ // Moving messages on the same arena should lead to swapped pointers.
+ *message2_on_arena = std::move(*message1_on_arena);
+ EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveDifferentArenas) {
+ Arena arena1, arena2;
+
+ auto* message1_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena1);
+ TestUtil::SetAllFields(message1_on_arena);
+ const auto* nested = &message1_on_arena->optional_nested_message();
+
+ auto* message2_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena2);
+
+ // Moving messages on two different arenas should lead to a copy.
+ *message2_on_arena = std::move(*message1_on_arena);
+ EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+ TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+ TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, MoveFromArena) {
+ Arena arena;
+
+ auto* message1_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+ TestUtil::SetAllFields(message1_on_arena);
+ const auto* nested = &message1_on_arena->optional_nested_message();
+
+ protobuf_unittest::TestAllTypes message2;
+
+ // Moving from a message on the arena should lead to a copy.
+ message2 = std::move(*message1_on_arena);
+ EXPECT_NE(nested, &message2.optional_nested_message());
+ TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(MovableMessageTest, MoveToArena) {
+ Arena arena;
+
+ protobuf_unittest::TestAllTypes message1;
+ TestUtil::SetAllFields(&message1);
+ const auto* nested = &message1.optional_nested_message();
+
+ auto* message2_on_arena =
+ Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+ // Moving to a message on the arena should lead to a copy.
+ *message2_on_arena = std::move(message1);
+ EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+ TestUtil::ExpectAllFieldsSet(message1);
+ TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, Noexcept) {
+ EXPECT_TRUE(
+ std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
+ EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
+}
+
+#endif // LANG_CXX11
+
+} // namespace cpp_unittest
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_names.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_names.h
new file mode 100644
index 00000000..81090017
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_names.h
@@ -0,0 +1,96 @@
+// 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_CPP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+
+#include <string>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class EnumValueDescriptor;
+class FieldDescriptor;
+
+namespace compiler {
+namespace cpp {
+
+// Returns the unqualified C++ name.
+//
+// For example, if you had:
+// package foo.bar;
+// message Baz { message Qux {} }
+// Then the non-qualified version would be:
+// Baz_Qux
+std::string ClassName(const Descriptor* descriptor);
+std::string ClassName(const EnumDescriptor* enum_descriptor);
+
+// Returns the fully qualified C++ name.
+//
+// For example, if you had:
+// package foo.bar;
+// message Baz { message Qux {} }
+// Then the qualified ClassName for Qux would be:
+// ::foo::bar::Baz_Qux
+std::string QualifiedClassName(const Descriptor* d);
+std::string QualifiedClassName(const EnumDescriptor* d);
+std::string QualifiedExtensionName(const FieldDescriptor* d);
+
+// 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().
+std::string FieldName(const FieldDescriptor* field);
+
+// Requires that this field is in a oneof. Returns the (unqualified) case
+// constant for this field.
+std::string OneofCaseConstantName(const FieldDescriptor* field);
+// Returns the quafilied case constant for this field.
+std::string QualifiedOneofCaseConstantName(const FieldDescriptor* field);
+
+// Get the (unqualified) name that should be used for this enum value in C++
+// code.
+std::string EnumValueName(const EnumValueDescriptor* enum_value);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_options.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 00000000..d0f16d03
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_options.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: rennie@google.com (Jeffrey Rennie)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+
+#include <set>
+#include <string>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+class AccessInfoMap;
+
+namespace cpp {
+
+enum class EnforceOptimizeMode {
+ kNoEnforcement, // Use the runtime specified by the file specific options.
+ kSpeed, // Full runtime with a generated code implementation.
+ kCodeSize, // Full runtime with a reflective implementation.
+ kLiteRuntime,
+};
+
+struct FieldListenerOptions {
+ bool inject_field_listener_events = false;
+ std::set<std::string> forbidden_field_listener_events;
+};
+
+// Generator options (see generator.cc for a description of each):
+struct Options {
+ std::string dllexport_decl;
+ bool safe_boundary_check = false;
+ bool proto_h = false;
+ bool transitive_pb_h = true;
+ bool annotate_headers = false;
+ EnforceOptimizeMode enforce_mode = EnforceOptimizeMode::kNoEnforcement;
+ bool table_driven_parsing = false;
+ bool table_driven_serialization = false;
+ bool lite_implicit_weak_fields = false;
+ bool bootstrap = false;
+ bool opensource_runtime = false;
+ bool annotate_accessor = false;
+ bool unused_field_stripping = false;
+ bool profile_driven_inline_string = true;
+ bool force_inline_string = false;
+ std::string runtime_include_base;
+ int num_cc_files = 0;
+ std::string annotation_pragma_name;
+ std::string annotation_guard_name;
+ const AccessInfoMap* access_info_map = nullptr;
+ enum {
+ kTCTableNever,
+ kTCTableGuarded,
+ kTCTableAlways
+ } tctable_mode = kTCTableNever;
+ FieldListenerOptions field_listener_options;
+ bool eagerly_verified_lazy = false;
+ bool force_eagerly_verified_lazy = false;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.cc
new file mode 100644
index 00000000..a6384a7f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.cc
@@ -0,0 +1,228 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <compiler/cpp/cpp_padding_optimizer.h>
+
+#include <compiler/cpp/cpp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+// FieldGroup is just a helper for PaddingOptimizer below. It holds a vector of
+// fields that are grouped together because they have compatible alignment, and
+// a preferred location in the final field ordering.
+class FieldGroup {
+ public:
+ FieldGroup() : preferred_location_(0) {}
+
+ // A group with a single field.
+ FieldGroup(float preferred_location, const FieldDescriptor* field)
+ : preferred_location_(preferred_location), fields_(1, field) {}
+
+ // Append the fields in 'other' to this group.
+ void Append(const FieldGroup& other) {
+ if (other.fields_.empty()) {
+ return;
+ }
+ // Preferred location is the average among all the fields, so we weight by
+ // the number of fields on each FieldGroup object.
+ preferred_location_ = (preferred_location_ * fields_.size() +
+ (other.preferred_location_ * other.fields_.size())) /
+ (fields_.size() + other.fields_.size());
+ fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
+ }
+
+ void SetPreferredLocation(float location) { preferred_location_ = location; }
+ const std::vector<const FieldDescriptor*>& fields() const { return fields_; }
+
+ // FieldGroup objects sort by their preferred location.
+ bool operator<(const FieldGroup& other) const {
+ return preferred_location_ < other.preferred_location_;
+ }
+
+ private:
+ // "preferred_location_" is an estimate of where this group should go in the
+ // final list of fields. We compute this by taking the average index of each
+ // field in this group in the original ordering of fields. This is very
+ // approximate, but should put this group close to where its member fields
+ // originally went.
+ float preferred_location_;
+ std::vector<const FieldDescriptor*> fields_;
+ // We rely on the default copy constructor and operator= so this type can be
+ // used in a vector.
+};
+
+} // namespace
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, fields of similar family (see below) are together and within each
+// family, alignment padding is minimized.
+//
+// We try to do this while keeping each field as close as possible to its field
+// number order so that we don't reduce cache locality much for function that
+// access each field in order. Originally, OptimizePadding used declaration
+// order for its decisions, but generated code minus the serializer/parsers uses
+// the output of OptimizePadding as well (stored in
+// MessageGenerator::optimized_order_). Since the serializers use field number
+// order, we use that as a tie-breaker.
+//
+// We classify each field into a particular "family" of fields, that we perform
+// the same operation on in our generated functions.
+//
+// REPEATED is placed first, as the C++ compiler automatically initializes
+// these fields in layout order.
+//
+// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
+// calls ArenaStringPtr::Destroy on each.
+//
+// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset
+// non-repeated fields otherwise.
+//
+// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
+// delete on each. We initialize these fields with a NULL pointer (see
+// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
+// memset.
+//
+// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
+//
+// OTHER these fields are initialized one-by-one.
+void PaddingOptimizer::OptimizeLayout(
+ std::vector<const FieldDescriptor*>* fields, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ // The sorted numeric order of Family determines the declaration order in the
+ // memory layout.
+ enum Family {
+ REPEATED = 0,
+ STRING = 1,
+ // Laying out LAZY_MESSAGE before MESSAGE allows a single memset to zero
+ // MESSAGE and ZERO_INITIALIZABLE fields together.
+ LAZY_MESSAGE = 2,
+ MESSAGE = 3,
+ ZERO_INITIALIZABLE = 4,
+ OTHER = 5,
+ kMaxFamily
+ };
+
+ // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+ std::vector<FieldGroup> aligned_to_1[kMaxFamily];
+ std::vector<FieldGroup> aligned_to_4[kMaxFamily];
+ std::vector<FieldGroup> aligned_to_8[kMaxFamily];
+ for (int i = 0; i < fields->size(); ++i) {
+ const FieldDescriptor* field = (*fields)[i];
+
+ Family f = OTHER;
+ if (field->is_repeated()) {
+ f = REPEATED;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ f = STRING;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ f = MESSAGE;
+ if (IsLazy(field, options, scc_analyzer)) {
+ f = LAZY_MESSAGE;
+ }
+ } else if (CanInitializeByZeroing(field)) {
+ f = ZERO_INITIALIZABLE;
+ }
+
+ const int j = field->number();
+ switch (EstimateAlignmentSize(field)) {
+ case 1:
+ aligned_to_1[f].push_back(FieldGroup(j, field));
+ break;
+ case 4:
+ aligned_to_4[f].push_back(FieldGroup(j, field));
+ break;
+ case 8:
+ aligned_to_8[f].push_back(FieldGroup(j, field));
+ break;
+ default:
+ GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field)
+ << "for a field " << field->full_name() << ".";
+ }
+ }
+
+ // For each family, group fields to optimize padding.
+ for (int f = 0; f < kMaxFamily; f++) {
+ // Now group fields aligned to 1 byte into sets of 4, and treat those like a
+ // single field aligned to 4 bytes.
+ for (int i = 0; i < aligned_to_1[f].size(); i += 4) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
+ field_group.Append(aligned_to_1[f][j]);
+ }
+ aligned_to_4[f].push_back(field_group);
+ }
+ // Sort by preferred location to keep fields as close to their field number
+ // order as possible. Using stable_sort ensures that the output is
+ // consistent across runs.
+ std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end());
+
+ // Now group fields aligned to 4 bytes (or the 4-field groups created above)
+ // into pairs, and treat those like a single field aligned to 8 bytes.
+ for (int i = 0; i < aligned_to_4[f].size(); i += 2) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
+ field_group.Append(aligned_to_4[f][j]);
+ }
+ if (i == aligned_to_4[f].size() - 1) {
+ if (f == OTHER) {
+ // Move incomplete 4-byte block to the beginning. This is done to
+ // pair with the (possible) leftover blocks from the
+ // ZERO_INITIALIZABLE family.
+ field_group.SetPreferredLocation(-1);
+ } else {
+ // Move incomplete 4-byte block to the end.
+ field_group.SetPreferredLocation(fields->size() + 1);
+ }
+ }
+ aligned_to_8[f].push_back(field_group);
+ }
+ // Sort by preferred location.
+ std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
+ }
+
+ // Now pull out all the FieldDescriptors in order.
+ fields->clear();
+ for (int f = 0; f < kMaxFamily; ++f) {
+ for (int i = 0; i < aligned_to_8[f].size(); ++i) {
+ fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(),
+ aligned_to_8[f][i].fields().end());
+ }
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.h
new file mode 100644
index 00000000..c08fa8dc
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_padding_optimizer.h
@@ -0,0 +1,65 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: seongkim@google.com (Seong Beom Kim)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
+
+#include <compiler/cpp/cpp_message_layout_helper.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Rearranges the fields of a message to minimize padding.
+// Fields are grouped by the type and the size.
+// For example, grouping four boolean fields and one int32
+// field results in zero padding overhead. See OptimizeLayout's
+// comment for details.
+class PaddingOptimizer : public MessageLayoutHelper {
+ public:
+ PaddingOptimizer() {}
+ ~PaddingOptimizer() override {}
+
+ void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) override;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.cc
new file mode 100644
index 00000000..8eed2224
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.cc
@@ -0,0 +1,1303 @@
+// 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 <compiler/cpp/cpp_parse_function_generator.h>
+
+#include <algorithm>
+#include <limits>
+#include <string>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+using google::protobuf::internal::TcFieldData;
+using google::protobuf::internal::WireFormat;
+using google::protobuf::internal::WireFormatLite;
+
+std::vector<const FieldDescriptor*> GetOrderedFields(
+ const Descriptor* descriptor, const Options& options) {
+ std::vector<const FieldDescriptor*> ordered_fields;
+ for (auto field : FieldRange(descriptor)) {
+ if (!IsFieldStripped(field, options)) {
+ ordered_fields.push_back(field);
+ }
+ }
+ std::sort(ordered_fields.begin(), ordered_fields.end(),
+ [](const FieldDescriptor* a, const FieldDescriptor* b) {
+ return a->number() < b->number();
+ });
+ return ordered_fields;
+}
+
+bool HasInternalAccessors(const FieldOptions::CType ctype) {
+ return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
+}
+
+int TagSize(uint32_t field_number) {
+ if (field_number < 16) return 1;
+ GOOGLE_CHECK_LT(field_number, (1 << 14))
+ << "coded tag for " << field_number << " too big for uint16_t";
+ return 2;
+}
+
+const char* CodedTagType(int tag_size) {
+ return tag_size == 1 ? "uint8_t" : "uint16_t";
+}
+
+const char* TagType(const FieldDescriptor* field) {
+ return CodedTagType(TagSize(field->number()));
+}
+
+std::string TcParserName(const Options& options) {
+ return StrCat("::", ProtobufNamespace(options),
+ "::internal::TcParser::");
+}
+
+std::string MessageTcParseFunctionName(const FieldDescriptor* field,
+ const Options& options) {
+ if (field->message_type()->field_count() == 0 ||
+ !HasGeneratedMethods(field->message_type()->file(), options)) {
+ // For files with `option optimize_for = CODE_SIZE`, or which derive from
+ // `ZeroFieldsBase`, we need to call the `_InternalParse` function, because
+ // there is no generated tailcall function. For tailcall parsing, this is
+ // done by helpers in TcParser.
+ return StrCat(TcParserName(options),
+ (field->is_repeated() ? "Repeated" : "Singular"),
+ "ParseMessage<",
+ QualifiedClassName(field->message_type()), //
+ ", ", TagType(field), ">");
+ }
+ // This matches macros in generated_message_tctable_impl.h:
+ return StrCat("PROTOBUF_TC_PARSE_",
+ (field->is_repeated() ? "REPEATED" : "SINGULAR"),
+ TagSize(field->number()), "(",
+ QualifiedClassName(field->message_type()), ")");
+}
+
+std::string FieldParseFunctionName(const FieldDescriptor* field,
+ const Options& options);
+
+} // namespace
+
+TailCallTableInfo::TailCallTableInfo(const Descriptor* descriptor,
+ const Options& options,
+ const std::vector<int>& has_bit_indices,
+ MessageSCCAnalyzer* scc_analyzer) {
+ std::vector<const FieldDescriptor*> ordered_fields =
+ GetOrderedFields(descriptor, options);
+
+ // The table size is rounded up to the nearest power of 2, clamping at 2^5.
+ // Note that this is a naive approach: a better approach should only consider
+ // table-eligible fields. We may also want to push rarely-encountered fields
+ // into the fallback, to make the table smaller.
+ table_size_log2 = ordered_fields.size() >= 16 ? 5
+ : ordered_fields.size() >= 8 ? 4
+ : ordered_fields.size() >= 4 ? 3
+ : ordered_fields.size() >= 2 ? 2
+ : 1;
+ const unsigned table_size = 1 << table_size_log2;
+
+ // Construct info for each possible entry. Fields that do not use table-driven
+ // parsing will still have an entry that nominates the fallback function.
+ fast_path_fields.resize(table_size);
+
+ for (const auto* field : ordered_fields) {
+ // Eagerly assume slow path. If we can handle this field on the fast path,
+ // we will pop its entry from `fallback_fields`.
+ fallback_fields.push_back(field);
+
+ // Anything difficult slow path:
+ if (field->is_map()) continue;
+ if (field->real_containing_oneof()) continue;
+ if (field->options().weak()) continue;
+ if (IsImplicitWeakField(field, options, scc_analyzer)) continue;
+ if (IsLazy(field, options, scc_analyzer)) continue;
+
+ // The largest tag that can be read by the tailcall parser is two bytes
+ // when varint-coded. This allows 14 bits for the numeric tag value:
+ // byte 0 byte 1
+ // 1nnnnttt 0nnnnnnn
+ // ^^^^^^^ ^^^^^^^
+ uint32_t tag = WireFormat::MakeTag(field);
+ if (tag >= 1 << 14) {
+ continue;
+ } else if (tag >= 1 << 7) {
+ tag = ((tag << 1) & 0x7F00) | 0x80 | (tag & 0x7F);
+ }
+ // The field index is determined by the low bits of the field number, where
+ // the table size determines the width of the mask. The largest table
+ // supported is 32 entries. The parse loop uses these bits directly, so that
+ // the dispatch does not require arithmetic:
+ // byte 0 byte 1
+ // 1nnnnttt 0nnnnnnn
+ // ^^^^^
+ // This means that any field number that does not fit in the lower 4 bits
+ // will always have the top bit of its table index asserted:
+ uint32_t idx = (tag >> 3) & (table_size - 1);
+ // If this entry in the table is already used, then this field will be
+ // handled by the generated fallback function.
+ if (!fast_path_fields[idx].func_name.empty()) continue;
+
+ // Determine the hasbit mask for this field, if needed. (Note that fields
+ // without hasbits use different parse functions.)
+ int hasbit_idx;
+ if (HasHasbit(field)) {
+ hasbit_idx = has_bit_indices[field->index()];
+ GOOGLE_CHECK_NE(-1, hasbit_idx) << field->DebugString();
+ // The tailcall parser can only update the first 32 hasbits. If this
+ // field's has-bit is beyond that, then it will need to be handled by the
+ // fallback parse function.
+ if (hasbit_idx >= 32) continue;
+ } else {
+ // The tailcall parser only ever syncs 32 has-bits, so if there is no
+ // presence, set a bit that will not be used.
+ hasbit_idx = 63;
+ }
+
+ // Determine the name of the fastpath parse function to use for this field.
+ std::string name;
+
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_MESSAGE:
+ name = MessageTcParseFunctionName(field, options);
+ break;
+
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_BOOL:
+ name = FieldParseFunctionName(field, options);
+ break;
+
+ case FieldDescriptor::TYPE_BYTES:
+ if (field->options().ctype() == FieldOptions::STRING &&
+ field->default_value_string().empty() &&
+ !IsStringInlined(field, options)) {
+ name = FieldParseFunctionName(field, options);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (name.empty()) {
+ continue;
+ }
+ // This field made it into the fast path, so remove it from the fallback
+ // fields and fill in the table entry.
+ fallback_fields.pop_back();
+ fast_path_fields[idx].func_name = name;
+ fast_path_fields[idx].bits = TcFieldData(tag, hasbit_idx, 0);
+ fast_path_fields[idx].field = field;
+ }
+
+ // If there are no fallback fields, and at most one extension range, the
+ // parser can use a generic fallback function. Otherwise, a message-specific
+ // fallback routine is needed.
+ use_generated_fallback =
+ !fallback_fields.empty() || descriptor->extension_range_count() > 1;
+}
+
+ParseFunctionGenerator::ParseFunctionGenerator(
+ const Descriptor* descriptor, int max_has_bit_index,
+ const std::vector<int>& has_bit_indices,
+ const std::vector<int>& inlined_string_indices, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer,
+ const std::map<std::string, std::string>& vars)
+ : descriptor_(descriptor),
+ scc_analyzer_(scc_analyzer),
+ options_(options),
+ variables_(vars),
+ inlined_string_indices_(inlined_string_indices),
+ num_hasbits_(max_has_bit_index) {
+ if (should_generate_tctable()) {
+ tc_table_info_.reset(new TailCallTableInfo(descriptor_, options_,
+ has_bit_indices, scc_analyzer));
+ }
+ SetCommonVars(options_, &variables_);
+ SetUnknownFieldsVariable(descriptor_, options_, &variables_);
+ variables_["classname"] = ClassName(descriptor, false);
+}
+
+void ParseFunctionGenerator::GenerateMethodDecls(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ if (should_generate_tctable()) {
+ auto declare_function = [&format](const char* name,
+ const std::string& guard) {
+ if (!guard.empty()) {
+ format.Outdent();
+ format("#if $1$\n", guard);
+ format.Indent();
+ }
+ format("static const char* $1$(PROTOBUF_TC_PARAM_DECL);\n", name);
+ if (!guard.empty()) {
+ format.Outdent();
+ format("#endif // $1$\n", guard);
+ format.Indent();
+ }
+ };
+ if (should_generate_guarded_tctable()) {
+ format.Outdent();
+ format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ format.Indent();
+ }
+ format("// The Tct_* functions are internal to the protobuf runtime:\n");
+ // These guards are defined in port_def.inc:
+ declare_function("Tct_ParseS1", "PROTOBUF_TC_STATIC_PARSE_SINGULAR1");
+ declare_function("Tct_ParseS2", "PROTOBUF_TC_STATIC_PARSE_SINGULAR2");
+ declare_function("Tct_ParseR1", "PROTOBUF_TC_STATIC_PARSE_REPEATED1");
+ declare_function("Tct_ParseR2", "PROTOBUF_TC_STATIC_PARSE_REPEATED2");
+ if (tc_table_info_->use_generated_fallback) {
+ format.Outdent();
+ format(
+ " private:\n"
+ " ");
+ declare_function("Tct_ParseFallback", "");
+ format(" public:\n");
+ format.Indent();
+ }
+ if (should_generate_guarded_tctable()) {
+ format.Outdent();
+ format("#endif\n");
+ format.Indent();
+ }
+ }
+ format(
+ "const char* _InternalParse(const char* ptr, "
+ "::$proto_ns$::internal::ParseContext* ctx) final;\n");
+}
+
+void ParseFunctionGenerator::GenerateMethodImpls(io::Printer* printer) {
+ Formatter format(printer, variables_);
+ bool need_parse_function = true;
+ if (descriptor_->options().message_set_wire_format()) {
+ // Special-case MessageSet.
+ need_parse_function = false;
+ format(
+ "const char* $classname$::_InternalParse(const char* ptr,\n"
+ " ::$proto_ns$::internal::ParseContext* ctx) {\n"
+ "$annotate_deserialize$"
+ " return _extensions_.ParseMessageSet(ptr, \n"
+ " internal_default_instance(), &_internal_metadata_, ctx);\n"
+ "}\n");
+ }
+ if (!should_generate_tctable()) {
+ if (need_parse_function) {
+ GenerateLoopingParseFunction(format);
+ }
+ return;
+ }
+ if (should_generate_guarded_tctable()) {
+ format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n\n");
+ }
+ if (need_parse_function) {
+ GenerateTailcallParseFunction(format);
+ }
+ if (tc_table_info_->use_generated_fallback) {
+ GenerateTailcallFallbackFunction(format);
+ }
+ GenerateTailcallFieldParseFunctions(format);
+ if (should_generate_guarded_tctable()) {
+ if (need_parse_function) {
+ format("\n#else // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n\n");
+ GenerateLoopingParseFunction(format);
+ }
+ format("\n#endif // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ }
+}
+
+bool ParseFunctionGenerator::should_generate_tctable() const {
+ if (options_.tctable_mode == Options::kTCTableNever) {
+ return false;
+ }
+ return true;
+}
+
+void ParseFunctionGenerator::GenerateTailcallParseFunction(Formatter& format) {
+ GOOGLE_CHECK(should_generate_tctable());
+
+ // Generate an `_InternalParse` that starts the tail-calling loop.
+ format(
+ "const char* $classname$::_InternalParse(\n"
+ " const char* ptr, ::$proto_ns$::internal::ParseContext* ctx) {\n"
+ "$annotate_deserialize$"
+ " ptr = ::$proto_ns$::internal::TcParser::ParseLoop(\n"
+ " this, ptr, ctx, &_table_.header);\n");
+ format(
+ " return ptr;\n"
+ "}\n\n");
+}
+
+void ParseFunctionGenerator::GenerateTailcallFallbackFunction(
+ Formatter& format) {
+ GOOGLE_CHECK(should_generate_tctable());
+ format(
+ "const char* $classname$::Tct_ParseFallback(PROTOBUF_TC_PARAM_DECL) {\n"
+ "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr\n");
+ format.Indent();
+ format("auto* typed_msg = static_cast<$classname$*>(msg);\n");
+
+ if (num_hasbits_ > 0) {
+ // Sync hasbits
+ format("typed_msg->_has_bits_[0] = hasbits;\n");
+ }
+
+ format.Set("msg", "typed_msg->");
+ format.Set("this", "typed_msg");
+ format.Set("has_bits", "typed_msg->_has_bits_");
+ format.Set("next_tag", "goto next_tag");
+ GenerateParseIterationBody(format, descriptor_,
+ tc_table_info_->fallback_fields);
+
+ format.Outdent();
+ format(
+ "next_tag:\n"
+ "message_done:\n"
+ " return ptr;\n"
+ "#undef CHK_\n"
+ "}\n");
+}
+
+void ParseFunctionGenerator::GenerateTailcallFieldParseFunctions(
+ Formatter& format) {
+ GOOGLE_CHECK(should_generate_tctable());
+ // There are four cases where a tailcall target are needed for messages:
+ // {singular, repeated} x {1, 2}-byte tag
+ struct {
+ const char* type;
+ int size;
+ } const kTagLayouts[] = {
+ {"uint8_t", 1},
+ {"uint16_t", 2},
+ };
+ // Singular:
+ for (const auto& layout : kTagLayouts) {
+ // Guard macros are defined in port_def.inc.
+ format(
+ "#if PROTOBUF_TC_STATIC_PARSE_SINGULAR$1$\n"
+ "const char* $classname$::Tct_ParseS$1$(PROTOBUF_TC_PARAM_DECL) {\n"
+ " if (PROTOBUF_PREDICT_FALSE(data.coded_tag<$2$>() != 0))\n"
+ " PROTOBUF_MUSTTAIL "
+ "return table->fallback(PROTOBUF_TC_PARAM_PASS);\n"
+ " ptr += $1$;\n"
+ " hasbits |= (uint64_t{1} << data.hasbit_idx());\n"
+ " ::$proto_ns$::internal::TcParser::SyncHasbits"
+ "(msg, hasbits, table);\n"
+ " auto& field = ::$proto_ns$::internal::TcParser::"
+ "RefAt<$classtype$*>(msg, data.offset());\n"
+ " if (field == nullptr)\n"
+ " field = CreateMaybeMessage<$classtype$>(ctx->data().arena);\n"
+ " return ctx->ParseMessage(field, ptr);\n"
+ "}\n"
+ "#endif // PROTOBUF_TC_STATIC_PARSE_SINGULAR$1$\n",
+ layout.size, layout.type);
+ }
+ // Repeated:
+ for (const auto& layout : kTagLayouts) {
+ // Guard macros are defined in port_def.inc.
+ format(
+ "#if PROTOBUF_TC_STATIC_PARSE_REPEATED$1$\n"
+ "const char* $classname$::Tct_ParseR$1$(PROTOBUF_TC_PARAM_DECL) {\n"
+ " if (PROTOBUF_PREDICT_FALSE(data.coded_tag<$2$>() != 0)) {\n"
+ " PROTOBUF_MUSTTAIL "
+ "return table->fallback(PROTOBUF_TC_PARAM_PASS);\n"
+ " }\n"
+ " ptr += $1$;\n"
+ " auto& field = ::$proto_ns$::internal::TcParser::RefAt<"
+ "::$proto_ns$::RepeatedPtrField<$classname$>>(msg, data.offset());\n"
+ " ::$proto_ns$::internal::TcParser::SyncHasbits"
+ "(msg, hasbits, table);\n"
+ " ptr = ctx->ParseMessage(field.Add(), ptr);\n"
+ " return ptr;\n"
+ "}\n"
+ "#endif // PROTOBUF_TC_STATIC_PARSE_REPEATED$1$\n",
+ layout.size, layout.type);
+ }
+}
+
+void ParseFunctionGenerator::GenerateDataDecls(io::Printer* printer) {
+ if (!should_generate_tctable()) {
+ return;
+ }
+ Formatter format(printer, variables_);
+ if (should_generate_guarded_tctable()) {
+ format.Outdent();
+ format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ format.Indent();
+ }
+ format(
+ "static const ::$proto_ns$::internal::TcParseTable<$1$>\n"
+ " _table_;\n",
+ tc_table_info_->table_size_log2);
+ if (should_generate_guarded_tctable()) {
+ format.Outdent();
+ format("#endif // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ format.Indent();
+ }
+}
+
+void ParseFunctionGenerator::GenerateDataDefinitions(io::Printer* printer) {
+ if (!should_generate_tctable()) {
+ return;
+ }
+ Formatter format(printer, variables_);
+ if (should_generate_guarded_tctable()) {
+ format("#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ }
+ GenerateTailCallTable(format);
+ if (should_generate_guarded_tctable()) {
+ format("#endif // PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED\n");
+ }
+}
+
+void ParseFunctionGenerator::GenerateLoopingParseFunction(Formatter& format) {
+ format(
+ "const char* $classname$::_InternalParse(const char* ptr, "
+ "::$proto_ns$::internal::ParseContext* ctx) {\n"
+ "$annotate_deserialize$"
+ "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n");
+ format.Indent();
+ format.Set("msg", "");
+ format.Set("this", "this");
+ int hasbits_size = 0;
+ if (num_hasbits_ > 0) {
+ hasbits_size = (num_hasbits_ + 31) / 32;
+ }
+ // For now only optimize small hasbits.
+ if (hasbits_size != 1) hasbits_size = 0;
+ if (hasbits_size) {
+ format("_Internal::HasBits has_bits{};\n");
+ format.Set("has_bits", "has_bits");
+ } else {
+ format.Set("has_bits", "_has_bits_");
+ }
+ format.Set("next_tag", "continue");
+ format("while (!ctx->Done(&ptr)) {\n");
+ format.Indent();
+
+ GenerateParseIterationBody(format, descriptor_,
+ GetOrderedFields(descriptor_, options_));
+
+ format.Outdent();
+ format("} // while\n");
+
+ format.Outdent();
+ format("message_done:\n");
+ if (hasbits_size) format(" _has_bits_.Or(has_bits);\n");
+
+ format(
+ " return ptr;\n"
+ "failure:\n"
+ " ptr = nullptr;\n"
+ " goto message_done;\n"
+ "#undef CHK_\n"
+ "}\n");
+}
+
+void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) {
+ GOOGLE_CHECK(should_generate_tctable());
+ // All entries without a fast-path parsing function need a fallback.
+ std::string fallback;
+ if (tc_table_info_->use_generated_fallback) {
+ fallback = ClassName(descriptor_) + "::Tct_ParseFallback";
+ } else {
+ fallback = TcParserName(options_) + "GenericFallback";
+ if (GetOptimizeFor(descriptor_->file(), options_) ==
+ FileOptions::LITE_RUNTIME) {
+ fallback += "Lite";
+ }
+ }
+
+ // For simplicity and speed, the table is not covering all proto
+ // configurations. This model uses a fallback to cover all situations that
+ // the table can't accommodate, together with unknown fields or extensions.
+ // These are number of fields over 32, fields with 3 or more tag bytes,
+ // maps, weak fields, lazy, more than 1 extension range. In the cases
+ // the table is sufficient we can use a generic routine, that just handles
+ // unknown fields and potentially an extension range.
+ format(
+ "const ::$proto_ns$::internal::TcParseTable<$1$>\n"
+ " $classname$::_table_ = {\n",
+ tc_table_info_->table_size_log2);
+ {
+ auto table_scope = format.ScopedIndent();
+ format("{\n");
+ {
+ auto header_scope = format.ScopedIndent();
+ if (num_hasbits_ > 0 || IsMapEntryMessage(descriptor_)) {
+ format("PROTOBUF_FIELD_OFFSET($classname$, _has_bits_),\n");
+ } else {
+ format("0, // no _has_bits_\n");
+ }
+ if (descriptor_->extension_range_count() == 1) {
+ format(
+ "PROTOBUF_FIELD_OFFSET($classname$, _extensions_),\n"
+ "$1$, $2$, // extension_range_{low,high}\n",
+ descriptor_->extension_range(0)->start,
+ descriptor_->extension_range(0)->end);
+ } else {
+ format("0, 0, 0, // no _extensions_\n");
+ }
+ format(
+ "$1$, 0, $2$, // fast_idx_mask, reserved, num_fields\n"
+ "&$3$._instance,\n"
+ "$4$ // fallback\n",
+ (((1 << tc_table_info_->table_size_log2) - 1) << 3),
+ descriptor_->field_count(),
+ DefaultInstanceName(descriptor_, options_), fallback);
+ }
+ format("}, {\n");
+ {
+ auto fast_scope = format.ScopedIndent();
+ GenerateFastFieldEntries(format, fallback);
+ }
+ format("},\n"); // entries[]
+ }
+ format("};\n\n"); // _table_
+}
+
+void ParseFunctionGenerator::GenerateFastFieldEntries(
+ Formatter& format, const std::string& fallback) {
+ for (const auto& info : tc_table_info_->fast_path_fields) {
+ if (info.field != nullptr) {
+ PrintFieldComment(format, info.field);
+ }
+ format("{$1$, ", info.func_name.empty() ? fallback : info.func_name);
+ if (info.bits.data) {
+ GOOGLE_DCHECK_NE(nullptr, info.field);
+ format(
+ "{$1$, $2$, "
+ "static_cast<uint16_t>(PROTOBUF_FIELD_OFFSET($classname$, $3$_))}",
+ info.bits.coded_tag(), info.bits.hasbit_idx(), FieldName(info.field));
+ } else {
+ format("{}");
+ }
+ format("},\n");
+ }
+}
+
+void ParseFunctionGenerator::GenerateArenaString(Formatter& format,
+ const FieldDescriptor* field) {
+ if (HasHasbit(field)) {
+ format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
+ }
+ std::string default_string =
+ field->default_value_string().empty()
+ ? "::" + ProtobufNamespace(options_) +
+ "::internal::GetEmptyStringAlreadyInited()"
+ : QualifiedClassName(field->containing_type(), options_) +
+ "::" + MakeDefaultName(field) + ".get()";
+ format(
+ "if (arena != nullptr) {\n"
+ " ptr = ctx->ReadArenaString(ptr, &$msg$$name$_, arena");
+ if (IsStringInlined(field, options_)) {
+ GOOGLE_DCHECK(!inlined_string_indices_.empty());
+ int inlined_string_index = inlined_string_indices_[field->index()];
+ GOOGLE_DCHECK_GE(inlined_string_index, 0);
+ format(
+ ", $msg$_internal_$name$_donated()"
+ ", &$msg$_inlined_string_donated_[$1$]"
+ ", ~0x$2$u",
+ inlined_string_index / 32,
+ strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8));
+ } else {
+ GOOGLE_DCHECK(field->default_value_string().empty());
+ }
+ format(
+ ");\n"
+ "} else {\n"
+ " ptr = ::$proto_ns$::internal::InlineGreedyStringParser("
+ "$msg$$name$_.MutableNoArenaNoDefault(&$1$), ptr, ctx);\n"
+ "}\n"
+ "const std::string* str = &$msg$$name$_.Get(); (void)str;\n",
+ default_string);
+}
+
+void ParseFunctionGenerator::GenerateStrings(Formatter& format,
+ const FieldDescriptor* field,
+ bool check_utf8) {
+ FieldOptions::CType ctype = FieldOptions::STRING;
+ if (!options_.opensource_runtime) {
+ // Open source doesn't support other ctypes;
+ ctype = field->options().ctype();
+ }
+ if (!field->is_repeated() && !options_.opensource_runtime &&
+ GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
+ // For now only use arena string for strings with empty defaults.
+ field->default_value_string().empty() &&
+ !field->real_containing_oneof() && ctype == FieldOptions::STRING) {
+ GenerateArenaString(format, field);
+ } else {
+ std::string parser_name;
+ switch (ctype) {
+ case FieldOptions::STRING:
+ parser_name = "GreedyStringParser";
+ break;
+ case FieldOptions::CORD:
+ parser_name = "CordParser";
+ break;
+ case FieldOptions::STRING_PIECE:
+ parser_name = "StringPieceParser";
+ break;
+ }
+ format(
+ "auto str = $msg$$1$$2$_$name$();\n"
+ "ptr = ::$proto_ns$::internal::Inline$3$(str, ptr, ctx);\n",
+ HasInternalAccessors(ctype) ? "_internal_" : "",
+ field->is_repeated() && !field->is_packable() ? "add" : "mutable",
+ parser_name);
+ }
+ if (!check_utf8) return; // return if this is a bytes field
+ auto level = GetUtf8CheckMode(field, options_);
+ switch (level) {
+ case Utf8CheckMode::kNone:
+ return;
+ case Utf8CheckMode::kVerify:
+ format("#ifndef NDEBUG\n");
+ break;
+ case Utf8CheckMode::kStrict:
+ format("CHK_(");
+ break;
+ }
+ std::string field_name;
+ field_name = "nullptr";
+ if (HasDescriptorMethods(field->file(), options_)) {
+ field_name = StrCat("\"", field->full_name(), "\"");
+ }
+ format("::$proto_ns$::internal::VerifyUTF8(str, $1$)", field_name);
+ switch (level) {
+ case Utf8CheckMode::kNone:
+ return;
+ case Utf8CheckMode::kVerify:
+ format(
+ ";\n"
+ "#endif // !NDEBUG\n");
+ break;
+ case Utf8CheckMode::kStrict:
+ format(");\n");
+ break;
+ }
+}
+
+void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format,
+ const FieldDescriptor* field) {
+ if (field->is_packable()) {
+ if (field->type() == FieldDescriptor::TYPE_ENUM &&
+ !HasPreservingUnknownEnumSemantics(field)) {
+ std::string enum_type = QualifiedClassName(field->enum_type(), options_);
+ format(
+ "ptr = "
+ "::$proto_ns$::internal::Packed$1$Parser<$unknown_fields_type$>("
+ "$msg$_internal_mutable_$name$(), ptr, ctx, $2$_IsValid, "
+ "&$msg$_internal_metadata_, $3$);\n",
+ DeclaredTypeMethodName(field->type()), enum_type, field->number());
+ } else {
+ format(
+ "ptr = ::$proto_ns$::internal::Packed$1$Parser("
+ "$msg$_internal_mutable_$name$(), ptr, ctx);\n",
+ DeclaredTypeMethodName(field->type()));
+ }
+ } else {
+ auto field_type = field->type();
+ switch (field_type) {
+ case FieldDescriptor::TYPE_STRING:
+ GenerateStrings(format, field, true /* utf8 */);
+ break;
+ case FieldDescriptor::TYPE_BYTES:
+ GenerateStrings(format, field, false /* utf8 */);
+ break;
+ case FieldDescriptor::TYPE_MESSAGE: {
+ if (field->is_map()) {
+ const FieldDescriptor* val =
+ field->message_type()->FindFieldByName("value");
+ GOOGLE_CHECK(val);
+ if (val->type() == FieldDescriptor::TYPE_ENUM &&
+ !HasPreservingUnknownEnumSemantics(field)) {
+ format(
+ "auto object = "
+ "::$proto_ns$::internal::InitEnumParseWrapper<"
+ "$unknown_fields_type$>(&$msg$$name$_, $1$_IsValid, "
+ "$2$, &$msg$_internal_metadata_);\n"
+ "ptr = ctx->ParseMessage(&object, ptr);\n",
+ QualifiedClassName(val->enum_type(), options_),
+ field->number());
+ } else {
+ format("ptr = ctx->ParseMessage(&$msg$$name$_, ptr);\n");
+ }
+ } else if (IsLazy(field, options_, scc_analyzer_)) {
+ if (field->real_containing_oneof()) {
+ format(
+ "if (!$msg$_internal_has_$name$()) {\n"
+ " $msg$clear_$1$();\n"
+ " $msg$$1$_.$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
+ " ::$proto_ns$::internal::LazyField>("
+ "$msg$GetArenaForAllocation());\n"
+ " $msg$set_has_$name$();\n"
+ "}\n"
+ "auto* lazy_field = $msg$$1$_.$name$_;\n",
+ field->containing_oneof()->name());
+ } else if (HasHasbit(field)) {
+ format(
+ "_Internal::set_has_$name$(&$has_bits$);\n"
+ "auto* lazy_field = &$msg$$name$_;\n");
+ } else {
+ format("auto* lazy_field = &$msg$$name$_;\n");
+ }
+ format(
+ "::$proto_ns$::internal::LazyFieldParseHelper<\n"
+ " ::$proto_ns$::internal::LazyField> parse_helper(\n"
+ " $1$::default_instance(),\n"
+ " $msg$GetArenaForAllocation(), lazy_field);\n"
+ "ptr = ctx->ParseMessage(&parse_helper, ptr);\n",
+ FieldMessageTypeName(field, options_));
+ } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
+ if (!field->is_repeated()) {
+ format(
+ "ptr = ctx->ParseMessage(_Internal::mutable_$name$($this$), "
+ "ptr);\n");
+ } else {
+ format(
+ "ptr = ctx->ParseMessage($msg$$name$_.AddWeak("
+ "reinterpret_cast<const ::$proto_ns$::MessageLite*>($1$ptr_)"
+ "), ptr);\n",
+ QualifiedDefaultInstanceName(field->message_type(), options_));
+ }
+ } else if (IsWeak(field, options_)) {
+ format(
+ "{\n"
+ " auto* default_ = &reinterpret_cast<const Message&>($1$);\n"
+ " ptr = ctx->ParseMessage($msg$_weak_field_map_.MutableMessage("
+ "$2$, default_), ptr);\n"
+ "}\n",
+ QualifiedDefaultInstanceName(field->message_type(), options_),
+ field->number());
+ } else {
+ format(
+ "ptr = ctx->ParseMessage($msg$_internal_$mutable_field$(), "
+ "ptr);\n");
+ }
+ break;
+ }
+ default:
+ GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype "
+ << " filed type is " << field->type();
+ }
+ }
+}
+
+static bool ShouldRepeat(const FieldDescriptor* descriptor,
+ WireFormatLite::WireType wiretype) {
+ constexpr int kMaxTwoByteFieldNumber = 16 * 128;
+ return descriptor->number() < kMaxTwoByteFieldNumber &&
+ descriptor->is_repeated() &&
+ (!descriptor->is_packable() ||
+ wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+}
+
+void ParseFunctionGenerator::GenerateFieldBody(
+ Formatter& format, WireFormatLite::WireType wiretype,
+ const FieldDescriptor* field) {
+ Formatter::SaveState formatter_state(&format);
+ format.AddMap(
+ {{"name", FieldName(field)},
+ {"primitive_type", PrimitiveTypeName(options_, field->cpp_type())}});
+ if (field->is_repeated()) {
+ format.AddMap({{"put_field", StrCat("add_", FieldName(field))},
+ {"mutable_field", StrCat("add_", FieldName(field))}});
+ } else {
+ format.AddMap(
+ {{"put_field", StrCat("set_", FieldName(field))},
+ {"mutable_field", StrCat("mutable_", FieldName(field))}});
+ }
+ uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+ switch (wiretype) {
+ case WireFormatLite::WIRETYPE_VARINT: {
+ std::string type = PrimitiveTypeName(options_, field->cpp_type());
+ if (field->type() == FieldDescriptor::TYPE_ENUM) {
+ format.Set("enum_type",
+ QualifiedClassName(field->enum_type(), options_));
+ format(
+ "$uint64$ val = ::$proto_ns$::internal::ReadVarint64(&ptr);\n"
+ "CHK_(ptr);\n");
+ if (!HasPreservingUnknownEnumSemantics(field)) {
+ format("if (PROTOBUF_PREDICT_TRUE($enum_type$_IsValid(val))) {\n");
+ format.Indent();
+ }
+ format("$msg$_internal_$put_field$(static_cast<$enum_type$>(val));\n");
+ if (!HasPreservingUnknownEnumSemantics(field)) {
+ format.Outdent();
+ format(
+ "} else {\n"
+ " ::$proto_ns$::internal::WriteVarint("
+ "$1$, val, $msg$mutable_unknown_fields());\n"
+ "}\n",
+ field->number());
+ }
+ } else {
+ std::string size = (field->type() == FieldDescriptor::TYPE_INT32 ||
+ field->type() == FieldDescriptor::TYPE_SINT32 ||
+ field->type() == FieldDescriptor::TYPE_UINT32)
+ ? "32"
+ : "64";
+ std::string zigzag;
+ if ((field->type() == FieldDescriptor::TYPE_SINT32 ||
+ field->type() == FieldDescriptor::TYPE_SINT64)) {
+ zigzag = "ZigZag";
+ }
+ if (field->is_repeated() || field->real_containing_oneof()) {
+ format(
+ "$msg$_internal_$put_field$("
+ "::$proto_ns$::internal::ReadVarint$1$$2$(&ptr));\n"
+ "CHK_(ptr);\n",
+ zigzag, size);
+ } else {
+ if (HasHasbit(field)) {
+ format("_Internal::set_has_$name$(&$has_bits$);\n");
+ }
+ format(
+ "$msg$$name$_ = ::$proto_ns$::internal::ReadVarint$1$$2$(&ptr);\n"
+ "CHK_(ptr);\n",
+ zigzag, size);
+ }
+ }
+ break;
+ }
+ case WireFormatLite::WIRETYPE_FIXED32:
+ case WireFormatLite::WIRETYPE_FIXED64: {
+ if (field->is_repeated() || field->real_containing_oneof()) {
+ format(
+ "$msg$_internal_$put_field$("
+ "::$proto_ns$::internal::UnalignedLoad<$primitive_type$>(ptr));\n"
+ "ptr += sizeof($primitive_type$);\n");
+ } else {
+ if (HasHasbit(field)) {
+ format("_Internal::set_has_$name$(&$has_bits$);\n");
+ }
+ format(
+ "$msg$$name$_ = "
+ "::$proto_ns$::internal::UnalignedLoad<$primitive_type$>(ptr);\n"
+ "ptr += sizeof($primitive_type$);\n");
+ }
+ break;
+ }
+ case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+ GenerateLengthDelim(format, field);
+ format("CHK_(ptr);\n");
+ break;
+ }
+ case WireFormatLite::WIRETYPE_START_GROUP: {
+ format(
+ "ptr = ctx->ParseGroup($msg$_internal_$mutable_field$(), ptr, $1$);\n"
+ "CHK_(ptr);\n",
+ tag);
+ break;
+ }
+ case WireFormatLite::WIRETYPE_END_GROUP: {
+ GOOGLE_LOG(FATAL) << "Can't have end group field\n";
+ break;
+ }
+ } // switch (wire_type)
+}
+
+// Returns the tag for this field and in case of repeated packable fields,
+// sets a fallback tag in fallback_tag_ptr.
+static uint32_t ExpectedTag(const FieldDescriptor* field,
+ uint32_t* fallback_tag_ptr) {
+ uint32_t expected_tag;
+ if (field->is_packable()) {
+ auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
+ expected_tag = WireFormatLite::MakeTag(field->number(), expected_wiretype);
+ GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+ uint32_t fallback_tag =
+ WireFormatLite::MakeTag(field->number(), fallback_wiretype);
+
+ if (field->is_packed()) std::swap(expected_tag, fallback_tag);
+ *fallback_tag_ptr = fallback_tag;
+ } else {
+ auto expected_wiretype = WireFormat::WireTypeForField(field);
+ expected_tag = WireFormatLite::MakeTag(field->number(), expected_wiretype);
+ }
+ return expected_tag;
+}
+
+// These variables are used by the generated parse iteration, and must already
+// be defined in the generated code:
+// - `const char* ptr`: the input buffer.
+// - `ParseContext* ctx`: the associated context for `ptr`.
+// - implicit `this`: i.e., we must be in a non-static member function.
+//
+// The macro `CHK_(x)` must be defined. It should return an error condition if
+// the macro parameter is false.
+//
+// Whenever an END_GROUP tag was read, or tag 0 was read, the generated code
+// branches to the label `message_done`.
+//
+// These formatter variables are used:
+// - `next_tag`: a single statement to begin parsing the next tag.
+//
+// At the end of the generated code, the enclosing function should proceed to
+// parse the next tag in the stream.
+void ParseFunctionGenerator::GenerateParseIterationBody(
+ Formatter& format, const Descriptor* descriptor,
+ const std::vector<const FieldDescriptor*>& ordered_fields) {
+ format(
+ "$uint32$ tag;\n"
+ "ptr = ::$proto_ns$::internal::ReadTag(ptr, &tag);\n");
+
+ if (!ordered_fields.empty()) {
+ GenerateFieldSwitch(format, ordered_fields);
+ // Each field `case` only considers field number. Field numbers that are
+ // not defined in the message, or tags with an incompatible wire type, are
+ // considered "unusual" cases. They will be handled by the logic below.
+ format.Outdent();
+ format("handle_unusual:\n");
+ format.Indent();
+ }
+
+ // Unusual/extension/unknown case:
+ format(
+ "if ((tag == 0) || ((tag & 7) == 4)) {\n"
+ " CHK_(ptr);\n"
+ " ctx->SetLastTag(tag);\n"
+ " goto message_done;\n"
+ "}\n");
+ if (IsMapEntryMessage(descriptor)) {
+ format("$next_tag$;\n");
+ } else {
+ if (descriptor->extension_range_count() > 0) {
+ format("if (");
+ for (int i = 0; i < descriptor->extension_range_count(); i++) {
+ const Descriptor::ExtensionRange* range =
+ descriptor->extension_range(i);
+ if (i > 0) format(" ||\n ");
+
+ uint32_t start_tag = WireFormatLite::MakeTag(
+ range->start, static_cast<WireFormatLite::WireType>(0));
+ uint32_t end_tag = WireFormatLite::MakeTag(
+ range->end, static_cast<WireFormatLite::WireType>(0));
+
+ if (range->end > FieldDescriptor::kMaxNumber) {
+ format("($1$u <= tag)", start_tag);
+ } else {
+ format("($1$u <= tag && tag < $2$u)", start_tag, end_tag);
+ }
+ }
+ format(
+ ") {\n"
+ " ptr = $msg$_extensions_.ParseField(tag, ptr, "
+ "internal_default_instance(), &$msg$_internal_metadata_, ctx);\n"
+ " CHK_(ptr != nullptr);\n"
+ " $next_tag$;\n"
+ "}\n");
+ }
+ format(
+ "ptr = UnknownFieldParse(\n"
+ " tag,\n"
+ " $msg$_internal_metadata_.mutable_unknown_fields<"
+ "$unknown_fields_type$>(),\n"
+ " ptr, ctx);\n"
+ "CHK_(ptr != nullptr);\n");
+ }
+}
+
+void ParseFunctionGenerator::GenerateFieldSwitch(
+ Formatter& format,
+ const std::vector<const FieldDescriptor*>& ordered_fields) {
+ format("switch (tag >> 3) {\n");
+ format.Indent();
+
+ for (const auto* field : ordered_fields) {
+ PrintFieldComment(format, field);
+ format("case $1$:\n", field->number());
+ format.Indent();
+ uint32_t fallback_tag = 0;
+ uint32_t expected_tag = ExpectedTag(field, &fallback_tag);
+ format("if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
+ expected_tag & 0xFF);
+ format.Indent();
+ auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
+ uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
+ int tag_size = io::CodedOutputStream::VarintSize32(tag);
+ bool is_repeat = ShouldRepeat(field, wiretype);
+ if (is_repeat) {
+ format(
+ "ptr -= $1$;\n"
+ "do {\n"
+ " ptr += $1$;\n",
+ tag_size);
+ format.Indent();
+ }
+ GenerateFieldBody(format, wiretype, field);
+ if (is_repeat) {
+ format.Outdent();
+ format(
+ " if (!ctx->DataAvailable(ptr)) break;\n"
+ "} while (::$proto_ns$::internal::ExpectTag<$1$>(ptr));\n",
+ tag);
+ }
+ format.Outdent();
+ if (fallback_tag) {
+ format("} else if (static_cast<$uint8$>(tag) == $1$) {\n",
+ fallback_tag & 0xFF);
+ format.Indent();
+ GenerateFieldBody(format, WireFormatLite::GetTagWireType(fallback_tag),
+ field);
+ format.Outdent();
+ }
+ format(
+ "} else\n"
+ " goto handle_unusual;\n"
+ "$next_tag$;\n");
+ format.Outdent();
+ } // for loop over ordered fields
+
+ format(
+ "default:\n"
+ " goto handle_unusual;\n");
+ format.Outdent();
+ format("} // switch\n");
+}
+
+namespace {
+
+std::string FieldParseFunctionName(const FieldDescriptor* field,
+ const Options& options) {
+ ParseCardinality card = //
+ field->is_packed() ? ParseCardinality::kPacked
+ : field->is_repeated() ? ParseCardinality::kRepeated
+ : field->real_containing_oneof() ? ParseCardinality::kOneof
+ : ParseCardinality::kSingular;
+
+ TypeFormat type_format;
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_DOUBLE:
+ type_format = TypeFormat::kFixed64;
+ break;
+
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_FLOAT:
+ type_format = TypeFormat::kFixed32;
+ break;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ type_format = TypeFormat::kVar64;
+ break;
+
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ type_format = TypeFormat::kVar32;
+ break;
+
+ case FieldDescriptor::TYPE_SINT64:
+ type_format = TypeFormat::kSInt64;
+ break;
+
+ case FieldDescriptor::TYPE_SINT32:
+ type_format = TypeFormat::kSInt32;
+ break;
+
+ case FieldDescriptor::TYPE_BOOL:
+ type_format = TypeFormat::kBool;
+ break;
+
+ case FieldDescriptor::TYPE_BYTES:
+ type_format = TypeFormat::kBytes;
+ break;
+
+ case FieldDescriptor::TYPE_STRING:
+ switch (GetUtf8CheckMode(field, options)) {
+ case Utf8CheckMode::kNone:
+ type_format = TypeFormat::kBytes;
+ break;
+ case Utf8CheckMode::kStrict:
+ type_format = TypeFormat::kString;
+ break;
+ case Utf8CheckMode::kVerify:
+ type_format = TypeFormat::kStringValidateOnly;
+ break;
+ default:
+ GOOGLE_LOG(DFATAL) << "Mode not handled: "
+ << static_cast<int>(GetUtf8CheckMode(field, options));
+ return "";
+ }
+ break;
+
+ default:
+ GOOGLE_LOG(DFATAL) << "Type not handled: " << field->DebugString();
+ return "";
+ }
+
+ return "::" + ProtobufNamespace(options) + "::internal::TcParser::" +
+ GetTailCallFieldHandlerName(card, type_format,
+ TagSize(field->number()), options);
+}
+
+} // namespace
+
+std::string GetTailCallFieldHandlerName(ParseCardinality card,
+ TypeFormat type_format,
+ int tag_length_bytes,
+ const Options& options) {
+ std::string name;
+
+ // The field implementation functions are prefixed by cardinality:
+ // `Singular` for optional or implicit fields.
+ // `Repeated` for non-packed repeated.
+ // `Packed` for packed repeated.
+ switch (card) {
+ case ParseCardinality::kSingular:
+ name.append("Singular");
+ break;
+ case ParseCardinality::kOneof:
+ name.append("Oneof");
+ break;
+ case ParseCardinality::kRepeated:
+ name.append("Repeated");
+ break;
+ case ParseCardinality::kPacked:
+ name.append("Packed");
+ break;
+ }
+
+ // Next in the function name is the TypeFormat-specific name.
+ switch (type_format) {
+ case TypeFormat::kFixed64:
+ case TypeFormat::kFixed32:
+ name.append("Fixed");
+ break;
+
+ case TypeFormat::kVar64:
+ case TypeFormat::kVar32:
+ case TypeFormat::kSInt64:
+ case TypeFormat::kSInt32:
+ case TypeFormat::kBool:
+ name.append("Varint");
+ break;
+
+ case TypeFormat::kBytes:
+ case TypeFormat::kString:
+ case TypeFormat::kStringValidateOnly:
+ name.append("String");
+ break;
+
+ default:
+ break;
+ }
+
+ name.append("<");
+
+ // Determine the numeric layout type for the parser to use, independent of
+ // the specific parsing logic used.
+ switch (type_format) {
+ case TypeFormat::kVar64:
+ case TypeFormat::kFixed64:
+ name.append("uint64_t, ");
+ break;
+
+ case TypeFormat::kSInt64:
+ name.append("int64_t, ");
+ break;
+
+ case TypeFormat::kVar32:
+ case TypeFormat::kFixed32:
+ name.append("uint32_t, ");
+ break;
+
+ case TypeFormat::kSInt32:
+ name.append("int32_t, ");
+ break;
+
+ case TypeFormat::kBool:
+ name.append("bool, ");
+ break;
+
+ default:
+ break;
+ }
+
+ name.append(CodedTagType(tag_length_bytes));
+
+ switch (type_format) {
+ case TypeFormat::kVar64:
+ case TypeFormat::kVar32:
+ case TypeFormat::kBool:
+ StrAppend(&name, ", ", TcParserName(options), "kNoConversion");
+ break;
+
+ case TypeFormat::kSInt64:
+ case TypeFormat::kSInt32:
+ StrAppend(&name, ", ", TcParserName(options), "kZigZag");
+ break;
+
+ case TypeFormat::kBytes:
+ StrAppend(&name, ", ", TcParserName(options), "kNoUtf8");
+ break;
+
+ case TypeFormat::kString:
+ StrAppend(&name, ", ", TcParserName(options), "kUtf8");
+ break;
+
+ case TypeFormat::kStringValidateOnly:
+ StrAppend(&name, ", ", TcParserName(options), "kUtf8ValidateOnly");
+ break;
+
+ default:
+ break;
+ }
+
+ name.append(">");
+ return name;
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.h
new file mode 100644
index 00000000..54c0a36d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_parse_function_generator.h
@@ -0,0 +1,199 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_options.h>
+#include <io/printer.h>
+#include <descriptor.h>
+#include <generated_message_tctable_decl.h>
+#include <wire_format_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Helper class for generating tailcall parsing functions.
+struct TailCallTableInfo {
+ TailCallTableInfo(const Descriptor* descriptor, const Options& options,
+ const std::vector<int>& has_bit_indices,
+ MessageSCCAnalyzer* scc_analyzer);
+ // Information to generate field entries.
+ struct FieldInfo {
+ const FieldDescriptor* field;
+ google::protobuf::internal::TcFieldData bits;
+ std::string func_name;
+ };
+ // Fields parsed by the table fast-path.
+ std::vector<FieldInfo> fast_path_fields;
+ // Fields parsed by slow-path fallback.
+ std::vector<const FieldDescriptor*> fallback_fields;
+ // Table size.
+ int table_size_log2;
+ // Mask for has-bits of required fields.
+ uint32_t has_hasbits_required_mask;
+ // True if a generated fallback function is required instead of generic.
+ bool use_generated_fallback;
+};
+
+// ParseFunctionGenerator generates the _InternalParse function for a message
+// (and any associated supporting members).
+class ParseFunctionGenerator {
+ public:
+ ParseFunctionGenerator(const Descriptor* descriptor, int max_has_bit_index,
+ const std::vector<int>& has_bit_indices,
+ const std::vector<int>& inlined_string_indices,
+ const Options& options,
+ MessageSCCAnalyzer* scc_analyzer,
+ const std::map<std::string, std::string>& vars);
+
+ // Emits class-level method declarations to `printer`:
+ void GenerateMethodDecls(io::Printer* printer);
+
+ // Emits out-of-class method implementation definitions to `printer`:
+ void GenerateMethodImpls(io::Printer* printer);
+
+ // Emits class-level data member declarations to `printer`:
+ void GenerateDataDecls(io::Printer* printer);
+
+ // Emits out-of-class data member definitions to `printer`:
+ void GenerateDataDefinitions(io::Printer* printer);
+
+ private:
+ // Returns true if tailcall table code should be generated.
+ bool should_generate_tctable() const;
+
+ // Returns true if tailcall table code should be generated, but inside an
+ // #ifdef guard.
+ bool should_generate_guarded_tctable() const {
+ return should_generate_tctable() &&
+ options_.tctable_mode == Options::kTCTableGuarded;
+ }
+
+ // Generates a tail-calling `_InternalParse` function.
+ void GenerateTailcallParseFunction(Formatter& format);
+
+ // Generates a fallback function for tailcall table-based parsing.
+ void GenerateTailcallFallbackFunction(Formatter& format);
+
+ // Generates functions for parsing this message as a field.
+ void GenerateTailcallFieldParseFunctions(Formatter& format);
+
+ // Generates a looping `_InternalParse` function.
+ void GenerateLoopingParseFunction(Formatter& format);
+
+ // Generates the tail-call table definition.
+ void GenerateTailCallTable(Formatter& format);
+ void GenerateFastFieldEntries(Formatter& format, const std::string& fallback);
+
+ // Generates parsing code for an `ArenaString` field.
+ void GenerateArenaString(Formatter& format, const FieldDescriptor* field);
+
+ // Generates parsing code for a string-typed field.
+ void GenerateStrings(Formatter& format, const FieldDescriptor* field,
+ bool check_utf8);
+
+ // Generates parsing code for a length-delimited field (strings, messages,
+ // etc.).
+ void GenerateLengthDelim(Formatter& format, const FieldDescriptor* field);
+
+ // Generates the parsing code for a known field.
+ void GenerateFieldBody(Formatter& format,
+ google::protobuf::internal::WireFormatLite::WireType wiretype,
+ const FieldDescriptor* field);
+
+ // Generates code to parse the next field from the input stream.
+ void GenerateParseIterationBody(
+ Formatter& format, const Descriptor* descriptor,
+ const std::vector<const FieldDescriptor*>& ordered_fields);
+
+ // Generates a `switch` statement to parse each of `ordered_fields`.
+ void GenerateFieldSwitch(
+ Formatter& format,
+ const std::vector<const FieldDescriptor*>& ordered_fields);
+
+ const Descriptor* descriptor_;
+ MessageSCCAnalyzer* scc_analyzer_;
+ const Options& options_;
+ std::map<std::string, std::string> variables_;
+ std::unique_ptr<TailCallTableInfo> tc_table_info_;
+ std::vector<int> inlined_string_indices_;
+ int num_hasbits_;
+};
+
+enum class ParseCardinality {
+ kSingular,
+ kOneof,
+ kRepeated,
+ kPacked,
+};
+
+// TypeFormat defines parsing types, which encapsulates the expected wire
+// format, conversion or validation, and the in-memory layout.
+enum class TypeFormat {
+ // Fixed types:
+ kFixed64, // fixed64, sfixed64, double
+ kFixed32, // fixed32, sfixed32, float
+
+ // Varint types:
+ kVar64, // int64, uint64
+ kVar32, // int32, uint32
+ kSInt64, // sint64
+ kSInt32, // sint32
+ kBool, // bool
+
+ // Length-delimited types:
+ kBytes, // bytes
+ kString, // string (proto3/UTF-8 strict)
+ kStringValidateOnly, // string (proto2/UTF-8 validate only)
+};
+
+// Returns the name of a field parser function.
+//
+// These are out-of-line functions generated by
+// parse_function_inc_generator_main.
+std::string GetTailCallFieldHandlerName(ParseCardinality card,
+ TypeFormat type_format,
+ int tag_length_bytes,
+ const Options& options);
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_plugin_unittest.cc
new file mode 100644
index 00000000..3e7bebf7
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -0,0 +1,236 @@
+// 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>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/cpp/cpp_generator.h>
+#include <compiler/command_line_interface.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <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 std::string& parameter, GeneratorContext* context,
+ std::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_mutable:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_allocated: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_mutable:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_allocated: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.cc", "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 std::string& filename,
+ const std::string& insertion_point,
+ GeneratorContext* context) const {
+ std::unique_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));
+
+ CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ CppGenerator cpp_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ std::string proto_path = "-I" + TestTempDir();
+ std::string cpp_out = "--cpp_out=" + TestTempDir();
+ std::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
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.cc
new file mode 100644
index 00000000..06037b95
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -0,0 +1,505 @@
+// 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 <compiler/cpp/cpp_primitive_field.h>
+
+#include <compiler/cpp/cpp_helpers.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+using internal::WireFormatLite;
+
+namespace {
+
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32:
+ return -1;
+ case FieldDescriptor::TYPE_INT64:
+ return -1;
+ case FieldDescriptor::TYPE_UINT32:
+ return -1;
+ case FieldDescriptor::TYPE_UINT64:
+ return -1;
+ case FieldDescriptor::TYPE_SINT32:
+ return -1;
+ case FieldDescriptor::TYPE_SINT64:
+ return -1;
+ case FieldDescriptor::TYPE_FIXED32:
+ return WireFormatLite::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64:
+ return WireFormatLite::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32:
+ return WireFormatLite::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64:
+ return WireFormatLite::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT:
+ return WireFormatLite::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE:
+ return WireFormatLite::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return WireFormatLite::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM:
+ return -1;
+
+ case FieldDescriptor::TYPE_STRING:
+ return -1;
+ case FieldDescriptor::TYPE_BYTES:
+ return -1;
+ case FieldDescriptor::TYPE_GROUP:
+ return -1;
+ case FieldDescriptor::TYPE_MESSAGE:
+ return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
+ (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
+ (*variables)["default"] = DefaultValue(options, descriptor);
+ (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
+ int fixed_size = FixedSize(descriptor->type());
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = StrCat(fixed_size);
+ }
+ (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
+ static_cast<FieldDescriptorProto_Type>(descriptor->type()));
+ (*variables)["full_name"] = descriptor->full_name();
+}
+
+} // namespace
+
+// ===================================================================
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(descriptor, options) {
+ SetPrimitiveVariables(descriptor, &variables_, options);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+void PrimitiveFieldGenerator::GeneratePrivateMembers(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$type$ $name$_;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
+ "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
+ "private:\n"
+ "$type$ ${1$_internal_$name$$}$() const;\n"
+ "void ${1$_internal_set_$name$$}$($type$ value);\n"
+ "public:\n",
+ descriptor_);
+}
+
+void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline $type$ $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$($type$ value) {\n"
+ " $set_hasbit$\n"
+ " $name$_ = value;\n"
+ "}\n"
+ "inline void $classname$::set_$name$($type$ value) {\n"
+ " _internal_set_$name$(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("_internal_set_$name$(from._internal_$name$());\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("swap($name$_, other->$name$_);\n");
+}
+
+void PrimitiveFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_ = from.$name$_;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "target = stream->EnsureSpace(target);\n"
+ "target = "
+ "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
+ "$number$, this->_internal_$name$(), target);\n");
+}
+
+void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ int fixed_size = FixedSize(descriptor_->type());
+ if (fixed_size == -1) {
+ if (internal::WireFormat::TagSize(descriptor_->number(),
+ descriptor_->type()) == 1) {
+ // Adding one is very common and it turns out it can be done for
+ // free inside of WireFormatLite, so we can save an instruction here.
+ format(
+ "total_size += ::$proto_ns$::internal::WireFormatLite::"
+ "$declared_type$SizePlusOne(this->_internal_$name$());\n");
+ } else {
+ format(
+ "total_size += $tag_size$ +\n"
+ " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
+ " this->_internal_$name$());\n");
+ }
+ } else {
+ format("total_size += $tag_size$ + $fixed_size$;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_($default$)");
+}
+
+// ===================================================================
+
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : PrimitiveFieldGenerator(descriptor, options) {
+ SetCommonOneofFieldVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$() const {\n"
+ " if (_internal_has_$name$()) {\n"
+ " return $field_member$;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$($type$ value) {\n"
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " }\n"
+ " $field_member$ = value;\n"
+ "}\n"
+ "inline $type$ $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline void $classname$::set_$name$($type$ value) {\n"
+ " _internal_set_$name$(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$field_member$ = $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 {
+ Formatter format(printer, variables_);
+ format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(descriptor, options) {
+ SetPrimitiveVariables(descriptor, &variables_, options);
+
+ if (descriptor->is_packed()) {
+ variables_["packed_reader"] = "ReadPackedPrimitive";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
+ } else {
+ variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitive";
+ }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
+ if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "private:\n"
+ "$type$ ${1$_internal_$name$$}$(int index) const;\n"
+ "const ::$proto_ns$::RepeatedField< $type$ >&\n"
+ " ${1$_internal_$name$$}$() const;\n"
+ "void ${1$_internal_add_$name$$}$($type$ value);\n"
+ "::$proto_ns$::RepeatedField< $type$ >*\n"
+ " ${1$_internal_mutable_$name$$}$();\n"
+ "public:\n"
+ "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
+ "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
+ "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
+ " ${1$$name$$}$() const;\n"
+ "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
+ " ${1$mutable_$name$$}$();\n",
+ descriptor_);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline $type$ $classname$::_internal_$name$(int index) const {\n"
+ " return $name$_.Get(index);\n"
+ "}\n"
+ "inline $type$ $classname$::$name$(int index) const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$(index);\n"
+ "}\n"
+ "inline void $classname$::set_$name$(int index, $type$ value) {\n"
+ "$annotate_set$"
+ " $name$_.Set(index, value);\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::_internal_add_$name$($type$ value) {\n"
+ " $name$_.Add(value);\n"
+ "}\n"
+ "inline void $classname$::add_$name$($type$ value) {\n"
+ " _internal_add_$name$(value);\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ "}\n"
+ "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
+ "$classname$::_internal_$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ "$annotate_list$"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
+ "$classname$::_internal_mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ "$annotate_mutable_list$"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ " return _internal_mutable_$name$();\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.Clear();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.InternalSwap(&other->$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ // Not needed for repeated fields.
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.CopyFrom(from.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (descriptor_->is_packed()) {
+ if (FixedSize(descriptor_->type()) == -1) {
+ format(
+ "{\n"
+ " int byte_size = "
+ "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
+ " if (byte_size > 0) {\n"
+ " target = stream->Write$declared_type$Packed(\n"
+ " $number$, _internal_$name$(), byte_size, target);\n"
+ " }\n"
+ "}\n");
+ } else {
+ format(
+ "if (this->_internal_$name$_size() > 0) {\n"
+ " target = stream->WriteFixedPacked($number$, _internal_$name$(), "
+ "target);\n"
+ "}\n");
+ }
+ } else {
+ format(
+ "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
+ " target = stream->EnsureSpace(target);\n"
+ " target = ::$proto_ns$::internal::WireFormatLite::"
+ "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
+ "target);\n"
+ "}\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("{\n");
+ format.Indent();
+ int fixed_size = FixedSize(descriptor_->type());
+ if (fixed_size == -1) {
+ format(
+ "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
+ " $declared_type$Size(this->$name$_);\n");
+ } else {
+ format(
+ "unsigned int count = static_cast<unsigned "
+ "int>(this->_internal_$name$_size());\n"
+ "size_t data_size = $fixed_size$UL * count;\n");
+ }
+
+ if (descriptor_->is_packed()) {
+ format(
+ "if (data_size > 0) {\n"
+ " total_size += $tag_size$ +\n"
+ " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
+ " static_cast<$int32$>(data_size));\n"
+ "}\n");
+ if (FixedSize(descriptor_->type()) == -1) {
+ format(
+ "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
+ "_$name$_cached_byte_size_.store(cached_size,\n"
+ " std::memory_order_relaxed);\n");
+ }
+ format("total_size += data_size;\n");
+ } else {
+ format(
+ "total_size += $tag_size$ *\n"
+ " "
+ "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
+ "total_size += data_size;\n");
+ }
+ format.Outdent();
+ format("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_()");
+ if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
+ format("\n, _$name$_cached_byte_size_(0)");
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.h
new file mode 100644
index 00000000..28f18ce0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class PrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ ~PrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ 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) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ ~RepeatedPrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.cc
new file mode 100644
index 00000000..807a4cd9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.cc
@@ -0,0 +1,327 @@
+// 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 <compiler/cpp/cpp_service.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void InitMethodVariables(const MethodDescriptor* method, const Options& options,
+ Formatter* format) {
+ format->Set("name", method->name());
+ format->Set("input_type", QualifiedClassName(method->input_type(), options));
+ format->Set("output_type",
+ QualifiedClassName(method->output_type(), options));
+}
+
+} // namespace
+
+ServiceGenerator::ServiceGenerator(
+ const ServiceDescriptor* descriptor,
+ const std::map<std::string, std::string>& vars, const Options& options)
+ : descriptor_(descriptor), vars_(vars), options_(options) {
+ vars_["classname"] = descriptor_->name();
+ vars_["full_name"] = descriptor_->full_name();
+}
+
+ServiceGenerator::~ServiceGenerator() {}
+
+void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
+ Formatter format(printer, vars_);
+ // Forward-declare the stub type.
+ format(
+ "class $classname$_Stub;\n"
+ "\n");
+
+ GenerateInterface(printer);
+ GenerateStubDefinition(printer);
+}
+
+void ServiceGenerator::GenerateInterface(io::Printer* printer) {
+ Formatter format(printer, vars_);
+ format(
+ "class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {\n"
+ " protected:\n"
+ " // This class should be treated as an abstract interface.\n"
+ " inline $classname$() {};\n"
+ " public:\n"
+ " virtual ~$classname$();\n");
+ printer->Indent();
+
+ format(
+ "\n"
+ "typedef $classname$_Stub Stub;\n"
+ "\n"
+ "static const ::$proto_ns$::ServiceDescriptor* descriptor();\n"
+ "\n");
+
+ GenerateMethodSignatures(VIRTUAL, printer);
+
+ format(
+ "\n"
+ "// implements Service ----------------------------------------------\n"
+ "\n"
+ "const ::$proto_ns$::ServiceDescriptor* GetDescriptor();\n"
+ "void CallMethod(const ::$proto_ns$::MethodDescriptor* method,\n"
+ " ::$proto_ns$::RpcController* controller,\n"
+ " const ::$proto_ns$::Message* request,\n"
+ " ::$proto_ns$::Message* response,\n"
+ " ::google::protobuf::Closure* done);\n"
+ "const ::$proto_ns$::Message& GetRequestPrototype(\n"
+ " const ::$proto_ns$::MethodDescriptor* method) const;\n"
+ "const ::$proto_ns$::Message& GetResponsePrototype(\n"
+ " const ::$proto_ns$::MethodDescriptor* method) const;\n");
+
+ printer->Outdent();
+ format(
+ "\n"
+ " private:\n"
+ " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
+ "};\n"
+ "\n");
+}
+
+void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
+ Formatter format(printer, vars_);
+ format(
+ "class $dllexport_decl $$classname$_Stub : public $classname$ {\n"
+ " public:\n");
+
+ printer->Indent();
+
+ format(
+ "$classname$_Stub(::$proto_ns$::RpcChannel* channel);\n"
+ "$classname$_Stub(::$proto_ns$::RpcChannel* channel,\n"
+ " ::$proto_ns$::Service::ChannelOwnership ownership);\n"
+ "~$classname$_Stub();\n"
+ "\n"
+ "inline ::$proto_ns$::RpcChannel* channel() { return channel_; }\n"
+ "\n"
+ "// implements $classname$ ------------------------------------------\n"
+ "\n");
+
+ GenerateMethodSignatures(NON_VIRTUAL, printer);
+
+ printer->Outdent();
+ format(
+ " private:\n"
+ " ::$proto_ns$::RpcChannel* channel_;\n"
+ " bool owns_channel_;\n"
+ " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
+ "};\n"
+ "\n");
+}
+
+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);
+ Formatter format(printer, vars_);
+ InitMethodVariables(method, options_, &format);
+ format.Set("virtual", virtual_or_non == VIRTUAL ? "virtual " : "");
+ format(
+ "$virtual$void $name$(::$proto_ns$::RpcController* controller,\n"
+ " const $input_type$* request,\n"
+ " $output_type$* response,\n"
+ " ::google::protobuf::Closure* done);\n");
+ }
+}
+
+// ===================================================================
+
+void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
+ Formatter format(printer, vars_);
+ format(
+ "$classname$::~$classname$() {}\n"
+ "\n"
+ "const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n"
+ " "
+ "::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
+ " return $file_level_service_descriptors$[$1$];\n"
+ "}\n"
+ "\n"
+ "const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n"
+ " return descriptor();\n"
+ "}\n"
+ "\n",
+ index_in_metadata_);
+
+ // Generate methods of the interface.
+ GenerateNotImplementedMethods(printer);
+ GenerateCallMethod(printer);
+ GenerateGetPrototype(REQUEST, printer);
+ GenerateGetPrototype(RESPONSE, printer);
+
+ // Generate stub implementation.
+ format(
+ "$classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)\n"
+ " : channel_(channel), owns_channel_(false) {}\n"
+ "$classname$_Stub::$classname$_Stub(\n"
+ " ::$proto_ns$::RpcChannel* channel,\n"
+ " ::$proto_ns$::Service::ChannelOwnership ownership)\n"
+ " : channel_(channel),\n"
+ " owns_channel_(ownership == "
+ "::$proto_ns$::Service::STUB_OWNS_CHANNEL) "
+ "{}\n"
+ "$classname$_Stub::~$classname$_Stub() {\n"
+ " if (owns_channel_) delete channel_;\n"
+ "}\n"
+ "\n");
+
+ GenerateStubMethods(printer);
+}
+
+void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ Formatter format(printer, vars_);
+ InitMethodVariables(method, options_, &format);
+ format(
+ "void $classname$::$name$(::$proto_ns$::RpcController* controller,\n"
+ " const $input_type$*,\n"
+ " $output_type$*,\n"
+ " ::google::protobuf::Closure* done) {\n"
+ " controller->SetFailed(\"Method $name$() not implemented.\");\n"
+ " done->Run();\n"
+ "}\n"
+ "\n");
+ }
+}
+
+void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
+ Formatter format(printer, vars_);
+ format(
+ "void $classname$::CallMethod(const ::$proto_ns$::MethodDescriptor* "
+ "method,\n"
+ " ::$proto_ns$::RpcController* controller,\n"
+ " const ::$proto_ns$::Message* request,\n"
+ " ::$proto_ns$::Message* response,\n"
+ " ::google::protobuf::Closure* done) {\n"
+ " GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$1$]);\n"
+ " switch(method->index()) {\n",
+ index_in_metadata_);
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ Formatter format_method(printer, vars_);
+ InitMethodVariables(method, options_, &format_method);
+
+ // Note: down_cast does not work here because it only works on pointers,
+ // not references.
+ format_method(
+ " case $1$:\n"
+ " $name$(controller,\n"
+ " ::$proto_ns$::internal::DownCast<const $input_type$*>(\n"
+ " request),\n"
+ " ::$proto_ns$::internal::DownCast<$output_type$*>(\n"
+ " response),\n"
+ " done);\n"
+ " break;\n",
+ i);
+ }
+
+ format(
+ " default:\n"
+ " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
+ " break;\n"
+ " }\n"
+ "}\n"
+ "\n");
+}
+
+void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
+ io::Printer* printer) {
+ Formatter format(printer, vars_);
+ if (which == REQUEST) {
+ format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n");
+ } else {
+ format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n");
+ }
+
+ format(
+ " const ::$proto_ns$::MethodDescriptor* method) const {\n"
+ " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
+ " switch(method->index()) {\n");
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ const Descriptor* type =
+ (which == REQUEST) ? method->input_type() : method->output_type();
+
+ format(
+ " case $1$:\n"
+ " return $2$::default_instance();\n",
+ i, QualifiedClassName(type, options_));
+ }
+
+ format(
+ " default:\n"
+ " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
+ " return *::$proto_ns$::MessageFactory::generated_factory()\n"
+ " ->GetPrototype(method->$1$_type());\n"
+ " }\n"
+ "}\n"
+ "\n",
+ 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);
+ Formatter format(printer, vars_);
+ InitMethodVariables(method, options_, &format);
+ format(
+ "void $classname$_Stub::$name$(::$proto_ns$::RpcController* "
+ "controller,\n"
+ " const $input_type$* request,\n"
+ " $output_type$* response,\n"
+ " ::google::protobuf::Closure* done) {\n"
+ " channel_->CallMethod(descriptor()->method($1$),\n"
+ " controller, request, response, done);\n"
+ "}\n",
+ i);
+ }
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.h
new file mode 100644
index 00000000..7d1a1880
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_service.h
@@ -0,0 +1,122 @@
+// 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_SERVICE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
+
+#include <map>
+#include <string>
+#include <compiler/cpp/cpp_options.h>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class ServiceGenerator {
+ public:
+ // See generator.cc for the meaning of dllexport_decl.
+ explicit ServiceGenerator(const ServiceDescriptor* descriptor,
+ const std::map<std::string, std::string>& vars,
+ const Options& options);
+ ~ServiceGenerator();
+
+ // Header stuff.
+
+ // Generate the class definitions for the service's interface and the
+ // stub implementation.
+ void GenerateDeclarations(io::Printer* printer);
+
+ // Source file stuff.
+
+ // Generate implementations of everything declared by
+ // GenerateDeclarations().
+ void GenerateImplementation(io::Printer* printer);
+
+ private:
+ enum RequestOrResponse { REQUEST, RESPONSE };
+ enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };
+
+ // Header stuff.
+
+ // Generate the service abstract interface.
+ void GenerateInterface(io::Printer* printer);
+
+ // Generate the stub class definition.
+ void GenerateStubDefinition(io::Printer* printer);
+
+ // Prints signatures for all methods in the
+ void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
+ io::Printer* printer);
+
+ // Source file stuff.
+
+ // Generate the default implementations of the service methods, which
+ // produce a "not implemented" error.
+ void GenerateNotImplementedMethods(io::Printer* printer);
+
+ // Generate the CallMethod() method of the service.
+ void GenerateCallMethod(io::Printer* printer);
+
+ // Generate the Get{Request,Response}Prototype() methods.
+ void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
+
+ // Generate the stub's implementations of the service methods.
+ void GenerateStubMethods(io::Printer* printer);
+
+ const ServiceDescriptor* descriptor_;
+ std::map<std::string, std::string> vars_;
+ const Options& options_;
+
+ int index_in_metadata_;
+
+ friend class FileGenerator;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.cc
new file mode 100644
index 00000000..0faa2eea
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.cc
@@ -0,0 +1,915 @@
+// 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 <compiler/cpp/cpp_string_field.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+void SetStringVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
+ (*variables)["default"] = DefaultValue(options, descriptor);
+ (*variables)["default_length"] =
+ StrCat(descriptor->default_value_string().length());
+ std::string default_variable_string = MakeDefaultName(descriptor);
+ (*variables)["default_variable_name"] = default_variable_string;
+
+ if (!descriptor->default_value_string().empty()) {
+ (*variables)["lazy_variable"] =
+ QualifiedClassName(descriptor->containing_type(), options) +
+ "::" + default_variable_string;
+ }
+
+ (*variables)["default_string"] =
+ descriptor->default_value_string().empty()
+ ? "::" + (*variables)["proto_ns"] +
+ "::internal::GetEmptyStringAlreadyInited()"
+ : (*variables)["lazy_variable"] + ".get()";
+ (*variables)["init_value"] =
+ descriptor->default_value_string().empty()
+ ? "&::" + (*variables)["proto_ns"] +
+ "::internal::GetEmptyStringAlreadyInited()"
+ : "nullptr";
+ (*variables)["default_value_tag"] =
+ "::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" +
+ (descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") +
+ "Default{}";
+ (*variables)["default_variable_or_tag"] =
+ (*variables)[descriptor->default_value_string().empty()
+ ? "default_value_tag"
+ : "lazy_variable"];
+ (*variables)["pointer_type"] =
+ descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+ (*variables)["setter"] =
+ descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
+ (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
+ // 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();
+
+ if (options.opensource_runtime) {
+ (*variables)["string_piece"] = "::std::string";
+ } else {
+ (*variables)["string_piece"] = "::StringPiece";
+ }
+}
+
+} // namespace
+
+// ===================================================================
+
+StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(descriptor, options),
+ inlined_(IsStringInlined(descriptor, options)) {
+ SetStringVariables(descriptor, &variables_, options);
+}
+
+StringFieldGenerator::~StringFieldGenerator() {}
+
+void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (!inlined_) {
+ format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
+ } else {
+ // `_init_inline_xxx` is used for initializing default instances.
+ format(
+ "::$proto_ns$::internal::InlinedStringField $name$_;\n"
+ "static std::true_type _init_inline_$name$_;\n");
+ }
+}
+
+void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (!descriptor_->default_value_string().empty()) {
+ format(
+ "static const ::$proto_ns$::internal::LazyString"
+ " $default_variable_name$;\n");
+ }
+}
+
+void StringFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ // 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_, options_);
+
+ if (unknown_ctype) {
+ format.Outdent();
+ format(
+ " private:\n"
+ " // Hidden due to unknown ctype option.\n");
+ format.Indent();
+ }
+
+ format(
+ "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
+ "template <typename ArgT0 = const std::string&, typename... ArgT>\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
+ descriptor_);
+ format(
+ "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
+ "PROTOBUF_NODISCARD $deprecated_attr$std::string* "
+ "${1$$release_name$$}$();\n"
+ "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
+ "$name$);\n",
+ descriptor_);
+ format(
+ "private:\n"
+ "const std::string& _internal_$name$() const;\n"
+ "inline PROTOBUF_ALWAYS_INLINE void "
+ "_internal_set_$name$(const std::string& value);\n"
+ "std::string* _internal_mutable_$name$();\n");
+ if (inlined_) {
+ format(
+ "inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() "
+ "const;\n");
+ }
+ format("public:\n");
+
+ if (unknown_ctype) {
+ format.Outdent();
+ format(" public:\n");
+ format.Indent();
+ }
+}
+
+void StringFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline const std::string& $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n");
+ if (!descriptor_->default_value_string().empty()) {
+ format(
+ " if ($name$_.IsDefault(nullptr)) return "
+ "$default_variable_name$.get();\n");
+ }
+ format(
+ " return _internal_$name$();\n"
+ "}\n");
+ if (!inlined_) {
+ format(
+ "template <typename ArgT0, typename... ArgT>\n"
+ "inline PROTOBUF_ALWAYS_INLINE\n"
+ "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+ " $set_hasbit$\n"
+ " $name$_.$setter$($default_value_tag$, static_cast<ArgT0 &&>(arg0),"
+ " args..., GetArenaForAllocation());\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n");
+ } else {
+ format(
+ "template <typename ArgT0, typename... ArgT>\n"
+ "inline PROTOBUF_ALWAYS_INLINE\n"
+ "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+ " $set_hasbit$\n"
+ " $name$_.$setter$(nullptr, static_cast<ArgT0 &&>(arg0),"
+ " args..., GetArenaForAllocation(), _internal_$name$_donated(), "
+ "&$donating_states_word$, $mask_for_undonate$);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline bool $classname$::_internal_$name$_donated() const {\n"
+ " bool value = $inlined_string_donated$\n"
+ " return value;\n"
+ "}\n");
+ }
+ format(
+ "inline std::string* $classname$::mutable_$name$() {\n"
+ " std::string* _s = _internal_mutable_$name$();\n"
+ "$annotate_mutable$"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return _s;\n"
+ "}\n"
+ "inline const std::string& $classname$::_internal_$name$() const {\n"
+ " return $name$_.Get();\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$(const std::string& "
+ "value) {\n"
+ " $set_hasbit$\n");
+ if (!inlined_) {
+ format(
+ " $name$_.Set($default_value_tag$, value, GetArenaForAllocation());\n"
+ "}\n");
+ } else {
+ format(
+ " $name$_.Set(nullptr, value, GetArenaForAllocation(),\n"
+ " _internal_$name$_donated(), &$donating_states_word$, "
+ "$mask_for_undonate$);\n"
+ "}\n");
+ }
+ format(
+ "inline std::string* $classname$::_internal_mutable_$name$() {\n"
+ " $set_hasbit$\n");
+ if (!inlined_) {
+ format(
+ " return $name$_.Mutable($default_variable_or_tag$, "
+ "GetArenaForAllocation());\n"
+ "}\n");
+ } else {
+ format(
+ " return $name$_.Mutable($default_variable_or_tag$, "
+ "GetArenaForAllocation(), _internal_$name$_donated(), "
+ "&$donating_states_word$, $mask_for_undonate$);\n"
+ "}\n");
+ }
+ format(
+ "inline std::string* $classname$::$release_name$() {\n"
+ "$annotate_release$"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n");
+
+ if (HasHasbit(descriptor_)) {
+ format(
+ " if (!_internal_has_$name$()) {\n"
+ " return nullptr;\n"
+ " }\n"
+ " $clear_hasbit$\n");
+ if (!inlined_) {
+ format(
+ " auto* p = $name$_.ReleaseNonDefault($init_value$, "
+ "GetArenaForAllocation());\n");
+ if (descriptor_->default_value_string().empty()) {
+ format(
+ "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
+ " if ($name$_.IsDefault($init_value$)) {\n"
+ " $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
+ " }\n"
+ "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
+ }
+ format(" return p;\n");
+ } else {
+ format(
+ " return $name$_.Release(nullptr, GetArenaForAllocation(), "
+ "_internal_$name$_donated());\n");
+ }
+ } else {
+ format(
+ " return $name$_.Release($init_value$, GetArenaForAllocation());\n");
+ }
+
+ format(
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
+ " if ($name$ != nullptr) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n");
+ if (!inlined_) {
+ format(
+ " $name$_.SetAllocated($init_value$, $name$,\n"
+ " GetArenaForAllocation());\n");
+ if (descriptor_->default_value_string().empty()) {
+ format(
+ "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
+ " if ($name$_.IsDefault($init_value$)) {\n"
+ " $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
+ " }\n"
+ "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
+ }
+ } else {
+ // Currently, string fields with default value can't be inlined.
+ format(
+ " $name$_.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
+ "_internal_$name$_donated(), &$donating_states_word$, "
+ "$mask_for_undonate$);\n");
+ }
+ format(
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+}
+
+void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (!descriptor_->default_value_string().empty()) {
+ format(
+ "const ::$proto_ns$::internal::LazyString "
+ "$classname$::$default_variable_name$"
+ "{{{$default$, $default_length$}}, {nullptr}};\n");
+ }
+}
+
+void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (descriptor_->default_value_string().empty()) {
+ format("$name$_.ClearToEmpty();\n");
+ } else {
+ GOOGLE_DCHECK(!inlined_);
+ format(
+ "$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
+ }
+}
+
+void StringFieldGenerator::GenerateMessageClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ // 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 a hasbit, then the Clear() method of the protocol buffer
+ // will have checked that this field is set. If so, we can avoid redundant
+ // checks against the default variable.
+ const bool must_be_present = HasHasbit(descriptor_);
+
+ if (inlined_ && must_be_present) {
+ // Calling mutable_$name$() gives us a string reference and sets the has bit
+ // for $name$ (in proto2). We may get here when the string field is inlined
+ // but the string's contents have not been changed by the user, so we cannot
+ // make an assertion about the contents of the string and could never make
+ // an assertion about the string instance.
+ //
+ // For non-inlined strings, we distinguish from non-default by comparing
+ // instances, rather than contents.
+ format("$DCHK$(!$name$_.IsDefault(nullptr));\n");
+ }
+
+ if (descriptor_->default_value_string().empty()) {
+ if (must_be_present) {
+ format("$name$_.ClearNonDefaultToEmpty();\n");
+ } else {
+ format("$name$_.ClearToEmpty();\n");
+ }
+ } else {
+ // Clear to a non-empty default is more involved, as we try to use the
+ // Arena if one is present and may need to reallocate the string.
+ format(
+ "$name$_.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
+ }
+}
+
+void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ // TODO(gpike): improve this
+ format("_internal_set_$name$(from._internal_$name$());\n");
+}
+
+void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (!inlined_) {
+ format(
+ "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
+ " $init_value$,\n"
+ " &$name$_, lhs_arena,\n"
+ " &other->$name$_, rhs_arena\n"
+ ");\n");
+ } else {
+ // At this point, it's guaranteed that the two fields being swapped are on
+ // the same arena.
+ format(
+ "$name$_.Swap(&other->$name$_, nullptr, GetArenaForAllocation(), "
+ "_internal_$name$_donated(), other->_internal_$name$_donated(), "
+ "&$donating_states_word$, &(other->$donating_states_word$), "
+ "$mask_for_undonate$);\n");
+ }
+}
+
+void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (inlined_ && descriptor_->default_value_string().empty()) {
+ // Automatic initialization will construct the string.
+ return;
+ }
+ GOOGLE_DCHECK(!inlined_);
+ format("$name$_.UnsafeSetDefault($init_value$);\n");
+ if (IsString(descriptor_, options_) &&
+ descriptor_->default_value_string().empty()) {
+ format(
+ "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
+ " $name$_.Set($init_value$, \"\", GetArenaForAllocation());\n"
+ "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
+ }
+}
+
+void StringFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ GenerateConstructorCode(printer);
+
+ if (HasHasbit(descriptor_)) {
+ format("if (from._internal_has_$name$()) {\n");
+ } else {
+ format("if (!from._internal_$name$().empty()) {\n");
+ }
+
+ format.Indent();
+
+ if (!inlined_) {
+ format(
+ "$name$_.Set($default_value_tag$, from._internal_$name$(), \n"
+ " GetArenaForAllocation());\n");
+ } else {
+ format(
+ "$name$_.Set(nullptr, from._internal_$name$(),\n"
+ " GetArenaForAllocation(), _internal_$name$_donated(), "
+ "&$donating_states_word$, $mask_for_undonate$);\n");
+ }
+
+ format.Outdent();
+ format("}\n");
+}
+
+void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (inlined_) {
+ // The destructor is automatically invoked.
+ return;
+ }
+
+ format("$name$_.DestroyNoArena($init_value$);\n");
+}
+
+void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, options_, false,
+ "this->_internal_$name$().data(), "
+ "static_cast<int>(this->_internal_$name$().length()),\n",
+ format);
+ }
+ format(
+ "target = stream->Write$declared_type$MaybeAliased(\n"
+ " $number$, this->_internal_$name$(), target);\n");
+}
+
+void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$ +\n"
+ " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
+ " this->_internal_$name$());\n");
+}
+
+void StringFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ if (inlined_) {
+ format("$name$_(nullptr, false)");
+ return;
+ }
+ if (descriptor_->default_value_string().empty()) {
+ format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)");
+ } else {
+ format("$name$_(nullptr)");
+ }
+}
+
+// ===================================================================
+
+StringOneofFieldGenerator::StringOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : StringFieldGenerator(descriptor, options) {
+ SetCommonOneofFieldVariables(descriptor, &variables_);
+ variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
+ variables_["oneof_index"] =
+ StrCat(descriptor->containing_oneof()->index());
+}
+
+StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
+
+void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline const std::string& $classname$::$name$() const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$();\n"
+ "}\n"
+ "template <typename ArgT0, typename... ArgT>\n"
+ "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $field_member$.UnsafeSetDefault($init_value$);\n"
+ " }\n"
+ " $field_member$.$setter$($default_value_tag$,"
+ " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline std::string* $classname$::mutable_$name$() {\n"
+ " std::string* _s = _internal_mutable_$name$();\n"
+ "$annotate_mutable$"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return _s;\n"
+ "}\n"
+ "inline const std::string& $classname$::_internal_$name$() const {\n"
+ " if (_internal_has_$name$()) {\n"
+ " return $field_member$.Get();\n"
+ " }\n"
+ " return $default_string$;\n"
+ "}\n"
+ "inline void $classname$::_internal_set_$name$(const std::string& "
+ "value) {\n"
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $field_member$.UnsafeSetDefault($init_value$);\n"
+ " }\n"
+ " $field_member$.Set($default_value_tag$, value, "
+ "GetArenaForAllocation());\n"
+ "}\n");
+ format(
+ "inline std::string* $classname$::_internal_mutable_$name$() {\n"
+ " if (!_internal_has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $field_member$.UnsafeSetDefault($init_value$);\n"
+ " }\n"
+ " return $field_member$.Mutable(\n"
+ " $default_variable_or_tag$, GetArenaForAllocation());\n"
+ "}\n"
+ "inline std::string* $classname$::$release_name$() {\n"
+ "$annotate_release$"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
+ " if (_internal_has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $field_member$.ReleaseNonDefault($init_value$, "
+ "GetArenaForAllocation());\n"
+ " } else {\n"
+ " return nullptr;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
+ " if (has_$oneof_name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " }\n"
+ " if ($name$ != nullptr) {\n"
+ " set_has_$name$();\n"
+ " $field_member$.UnsafeSetDefault($name$);\n"
+ " ::$proto_ns$::Arena* arena = GetArenaForAllocation();\n"
+ " if (arena != nullptr) {\n"
+ " arena->Own($name$);\n"
+ " }\n"
+ " }\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+}
+
+void StringOneofFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "$field_member$.Destroy($default_value_tag$, "
+ "GetArenaForAllocation());\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 {
+ // Nothing required here.
+}
+
+// ===================================================================
+
+RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(descriptor, options) {
+ SetStringVariables(descriptor, &variables_, options);
+}
+
+RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
+
+void RepeatedStringFieldGenerator::GeneratePrivateMembers(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ // See comment above about unknown ctypes.
+ bool unknown_ctype = descriptor_->options().ctype() !=
+ EffectiveStringCType(descriptor_, options_);
+
+ if (unknown_ctype) {
+ format.Outdent();
+ format(
+ " private:\n"
+ " // Hidden due to unknown ctype option.\n");
+ format.Indent();
+ }
+
+ format(
+ "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
+ "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
+ "std::string& value);\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
+ "value);\n"
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
+ "char* value);\n",
+ descriptor_);
+ if (!options_.opensource_runtime) {
+ format(
+ "$deprecated_attr$void ${1$set_$name$$}$(int index, "
+ "StringPiece value);\n",
+ descriptor_);
+ }
+ format(
+ "$deprecated_attr$void ${1$set_$name$$}$("
+ "int index, const $pointer_type$* value, size_t size);\n"
+ "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
+ "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
+ "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
+ "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
+ descriptor_);
+ if (!options_.opensource_runtime) {
+ format(
+ "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
+ descriptor_);
+ }
+ format(
+ "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
+ "value, size_t size)"
+ ";\n"
+ "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
+ "${1$$name$$}$() "
+ "const;\n"
+ "$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
+ "${1$mutable_$name$$}$()"
+ ";\n"
+ "private:\n"
+ "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
+ "std::string* _internal_add_$name$();\n"
+ "public:\n",
+ descriptor_);
+
+ if (unknown_ctype) {
+ format.Outdent();
+ format(" public:\n");
+ format.Indent();
+ }
+}
+
+void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "inline std::string* $classname$::add_$name$() {\n"
+ " std::string* _s = _internal_add_$name$();\n"
+ "$annotate_add_mutable$"
+ " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
+ " return _s;\n"
+ "}\n");
+ if (options_.safe_boundary_check) {
+ format(
+ "inline const std::string& $classname$::_internal_$name$(int index) "
+ "const {\n"
+ " return $name$_.InternalCheckedGet(\n"
+ " index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n");
+ } else {
+ format(
+ "inline const std::string& $classname$::_internal_$name$(int index) "
+ "const {\n"
+ " return $name$_.Get(index);\n"
+ "}\n");
+ }
+ format(
+ "inline const std::string& $classname$::$name$(int index) const {\n"
+ "$annotate_get$"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return _internal_$name$(index);\n"
+ "}\n"
+ "inline std::string* $classname$::mutable_$name$(int index) {\n"
+ "$annotate_mutable$"
+ " // @@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"
+ " $name$_.Mutable(index)->assign(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
+ " $name$_.Mutable(index)->assign(std::move(value));\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::set_$name$(int index, const char* value) {\n"
+ " $null_check$"
+ " $name$_.Mutable(index)->assign(value);\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n");
+ if (!options_.opensource_runtime) {
+ format(
+ "inline void "
+ "$classname$::set_$name$(int index, StringPiece value) {\n"
+ " $name$_.Mutable(index)->assign(value.data(), value.size());\n"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
+ "}\n");
+ }
+ format(
+ "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"
+ "$annotate_set$"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline std::string* $classname$::_internal_add_$name$() {\n"
+ " return $name$_.Add();\n"
+ "}\n"
+ "inline void $classname$::add_$name$(const std::string& value) {\n"
+ " $name$_.Add()->assign(value);\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::add_$name$(std::string&& value) {\n"
+ " $name$_.Add(std::move(value));\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::add_$name$(const char* value) {\n"
+ " $null_check$"
+ " $name$_.Add()->assign(value);\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add_char:$full_name$)\n"
+ "}\n");
+ if (!options_.opensource_runtime) {
+ format(
+ "inline void $classname$::add_$name$(StringPiece value) {\n"
+ " $name$_.Add()->assign(value.data(), value.size());\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
+ "}\n");
+ }
+ format(
+ "inline void "
+ "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
+ " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
+ "$annotate_add$"
+ " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
+ "}\n"
+ "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
+ "$classname$::$name$() const {\n"
+ "$annotate_list$"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
+ "$classname$::mutable_$name$() {\n"
+ "$annotate_mutable_list$"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ " return &$name$_;\n"
+ "}\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateClearingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.Clear();\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.MergeFrom(from.$name$_);\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateSwappingCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.InternalSwap(&other->$name$_);\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateConstructorCode(
+ io::Printer* printer) const {
+ // Not needed for repeated fields.
+}
+
+void RepeatedStringFieldGenerator::GenerateCopyConstructorCode(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_.CopyFrom(from.$name$_);");
+}
+
+void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
+ " const auto& s = this->_internal_$name$(i);\n");
+ // format("for (const std::string& s : this->$name$()) {\n");
+ format.Indent();
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(descriptor_, options_, false,
+ "s.data(), static_cast<int>(s.length()),\n",
+ format);
+ }
+ format.Outdent();
+ format(
+ " target = stream->Write$declared_type$($number$, s, target);\n"
+ "}\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateByteSize(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format(
+ "total_size += $tag_size$ *\n"
+ " ::$proto_ns$::internal::FromIntSize($name$_.size());\n"
+ "for (int i = 0, n = $name$_.size(); i < n; i++) {\n"
+ " total_size += "
+ "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
+ " $name$_.Get(i));\n"
+ "}\n");
+}
+
+void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
+ io::Printer* printer) const {
+ Formatter format(printer, variables_);
+ format("$name$_()");
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.h
new file mode 100644
index 00000000..c3240355
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_string_field.h
@@ -0,0 +1,127 @@
+// 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_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/cpp/cpp_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+class StringFieldGenerator : public FieldGenerator {
+ public:
+ StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ ~StringFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateStaticMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMessageClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateDestructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+ bool IsInlined() const override { return inlined_; }
+
+ private:
+ bool inlined_;
+ 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) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+
+ // StringFieldGenerator, from which we inherit, overrides this so we need to
+ // override it as well.
+ void GenerateMessageClearingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
+};
+
+class RepeatedStringFieldGenerator : public FieldGenerator {
+ public:
+ RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ ~RepeatedStringFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GeneratePrivateMembers(io::Printer* printer) const override;
+ void GenerateAccessorDeclarations(io::Printer* printer) const override;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer) const override;
+ void GenerateClearingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateSwappingCode(io::Printer* printer) const override;
+ void GenerateConstructorCode(io::Printer* printer) const override;
+ void GenerateCopyConstructorCode(io::Printer* printer) const override;
+ void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const override;
+ void GenerateByteSize(io::Printer* printer) const override;
+ void GenerateConstinitInitializer(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
new file mode 100644
index 00000000..466a8419
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -0,0 +1,184 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the C++ code generator.
+
+// LINT: LEGACY_NAMES
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+package protobuf_unittest;
+
+// Test that fields can have names like "input" and "i" which are also used
+// internally by the code generator for local variables.
+message TestConflictingSymbolNames {
+ message BuildDescriptors {}
+ message TypeTraits {}
+
+ optional int32 input = 1;
+ optional int32 output = 2;
+ optional string length = 3;
+ repeated int32 i = 4;
+ repeated string new_element = 5 [ctype = STRING_PIECE];
+ optional int32 total_size = 6;
+ optional int32 tag = 7;
+
+ enum TestEnum { FOO = 0; }
+ message Data1 {
+ repeated int32 data = 1;
+ }
+ message Data2 {
+ repeated TestEnum data = 1;
+ }
+ message Data3 {
+ repeated string data = 1;
+ }
+ message Data4 {
+ repeated Data4 data = 1;
+ }
+ message Data5 {
+ repeated string data = 1 [ctype = STRING_PIECE];
+ }
+ message Data6 {
+ repeated string data = 1 [ctype = CORD];
+ }
+
+ optional int32 source = 8;
+ optional int32 value = 9;
+ optional int32 file = 10;
+ optional int32 from = 11;
+ optional int32 handle_uninterpreted = 12;
+ repeated int32 index = 13;
+ optional int32 controller = 14;
+ optional int32 already_here = 15;
+
+ optional uint32 uint32 = 16;
+ optional uint64 uint64 = 17;
+ optional string string = 18;
+ optional int32 memset = 19;
+ optional int32 int32 = 20;
+ optional int64 int64 = 21;
+
+ optional uint32 cached_size = 22;
+ optional uint32 extensions = 23;
+ optional uint32 bit = 24;
+ optional uint32 bits = 25;
+ optional uint32 offsets = 26;
+ optional uint32 reflection = 27;
+
+ message Cord {}
+ optional string some_cord = 28 [ctype = CORD];
+
+ message StringPiece {}
+ optional string some_string_piece = 29 [ctype = STRING_PIECE];
+
+ // 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 {}
+ optional DO do = 32;
+
+ // Some template parameter names for extensions.
+ optional int32 field_type = 33;
+ optional bool is_packed = 34;
+
+ // 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 { // 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 while { // NO_PROTO3
+ default = 0; // 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 while conflicting_enum = 1; // NO_PROTO3
+} // NO_PROTO3
+
+enum bool { // NO_PROTO3
+ default = 0; // NO_PROTO3
+ NOT_EQ = 1; // NO_PROTO3
+ volatile = 2; // NO_PROTO3
+ return = 3; // NO_PROTO3
+} // NO_PROTO3
+
+message DummyMessage {}
+
+message NULL {
+ optional int32 int = 1;
+}
+
+extend TestConflictingSymbolNames { // NO_PROTO3
+ optional int32 void = 314253; // NO_PROTO3
+} // NO_PROTO3
+
+// Message names that could conflict.
+message Shutdown {}
+message TableStruct {}
+
+service TestConflictingMethodNames {
+ rpc Closure(DummyMessage) returns (DummyMessage);
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
new file mode 100644
index 00000000..cb6ca1b1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that proto2 compiler can generate valid code when the enum value
+// is INT_MAX. Note that this is a compile-only test and this proto is not
+// referenced in any C++ code.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message TestLargeEnumValue {
+ enum EnumWithLargeValue {
+ VALUE_1 = 1;
+ VALUE_MAX = 0x7fffffff;
+ }
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.cc
new file mode 100644
index 00000000..fa6f4d02
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.cc
@@ -0,0 +1,134 @@
+// 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.
+//
+// To test the code generator, we actually use it to generate code for
+// net/proto2/internal/unittest.proto, then test that. This means that we
+// are actually testing the parser and other parts of the system at the same
+// time, and that problems in the generator may show up as compile-time errors
+// rather than unittest failures, which may be surprising. However, testing
+// the output of the C++ generator directly would be very hard. We can't very
+// well just check it against golden files since those files would have to be
+// updated for any small change; such a test would be very brittle and probably
+// not very helpful. What we really want to test is that the code compiles
+// correctly and produces the interfaces we expect, which is why this test
+// is written this way.
+
+#include <compiler/cpp/cpp_unittest.h>
+
+#include <unittest.pb.h>
+#include <unittest_embed_optimize_for.pb.h>
+#include <unittest_optimize_for.pb.h>
+
+#include <test_util.h>
+
+#define MESSAGE_TEST_NAME MessageTest
+#define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
+#define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest
+#define GENERATED_ENUM_TEST_NAME GeneratedEnumTest
+#define GENERATED_SERVICE_TEST_NAME GeneratedServiceTest
+#define HELPERS_TEST_NAME HelpersTest
+#define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest
+
+#define UNITTEST_PROTO_PATH "net/proto2/internal/unittest.proto"
+#define UNITTEST ::protobuf_unittest
+#define UNITTEST_IMPORT ::protobuf_unittest_import
+
+// Must include after the above macros.
+#include <compiler/cpp/cpp_unittest.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+namespace protobuf_unittest = ::protobuf_unittest;
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) {
+ // test_bad_identifiers.proto successfully compiled, then it works. The
+ // following is just a token usage to insure that the code is, in fact,
+ // being compiled and linked.
+
+ protobuf_unittest::TestConflictingSymbolNames message;
+ message.set_uint32(1);
+ EXPECT_EQ(3, message.ByteSizeLong());
+
+ message.set_friend_(5);
+ EXPECT_EQ(5, message.friend_());
+
+ message.set_class_(6);
+ EXPECT_EQ(6, message.class_());
+
+ // Instantiate extension template functions to test conflicting template
+ // parameter names.
+ typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
+ message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
+ EXPECT_EQ(123, message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) {
+ protobuf_unittest::TestConflictingEnumNames message;
+ message.set_conflicting_enum(
+ protobuf_unittest::TestConflictingEnumNames_while_and_);
+ EXPECT_EQ(1, message.conflicting_enum());
+ message.set_conflicting_enum(
+ protobuf_unittest::TestConflictingEnumNames_while_XOR);
+ EXPECT_EQ(5, message.conflicting_enum());
+
+ protobuf_unittest::bool_ conflicting_enum;
+ conflicting_enum = protobuf_unittest::NOT_EQ;
+ EXPECT_EQ(1, conflicting_enum);
+ conflicting_enum = protobuf_unittest::return_;
+ EXPECT_EQ(3, conflicting_enum);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingMessageNames) {
+ protobuf_unittest::NULL_ message;
+ message.set_int_(123);
+ EXPECT_EQ(message.int_(), 123);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingExtension) {
+ protobuf_unittest::TestConflictingSymbolNames message;
+ message.SetExtension(protobuf_unittest::void_, 123);
+ EXPECT_EQ(123, message.GetExtension(protobuf_unittest::void_));
+}
+
+} // namespace cpp_unittest
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.h b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 00000000..c5dc767a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.h
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
+// any problems with the generated class names. We use this header to ensure
+// unittest.cc will declare the namespace prior to other includes, while obeying
+// normal include ordering.
+//
+// When generating a class name of "foo.Bar" we must ensure we prefix the class
+// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
+// trigger that case here by declaring google::protobuf::protobuf_unittest.
+//
+// See ClassName in helpers.h for more details.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+
+namespace google {
+namespace protobuf {
+namespace protobuf_unittest {}
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.inc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.inc
new file mode 100644
index 00000000..effb7de4
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/cpp_unittest.inc
@@ -0,0 +1,2234 @@
+// 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.
+//
+// To test the code generator, we actually use it to generate code for
+// net/proto2/internal/unittest.proto, then test that. This means that we
+// are actually testing the parser and other parts of the system at the same
+// time, and that problems in the generator may show up as compile-time errors
+// rather than unittest failures, which may be surprising. However, testing
+// the output of the C++ generator directly would be very hard. We can't very
+// well just check it against golden files since those files would have to be
+// updated for any small change; such a test would be very brittle and probably
+// not very helpful. What we really want to test is that the code compiles
+// correctly and produces the interfaces we expect, which is why this test
+// is written this way.
+
+#include <cstdint>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include <compiler/cpp/cpp_unittest.h>
+#include <stubs/strutil.h>
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// We exclude this large proto from cmake build because it's too large for
+// visual studio to compile (report internal errors).
+#include <unittest_enormous_descriptor.pb.h>
+#endif
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_test_bad_identifiers.pb.h>
+#include <compiler/scc.h>
+#include <compiler/importer.h>
+#include <test_util2.h>
+#include <unittest_no_generic_services.pb.h>
+#include <io/coded_stream.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.pb.h>
+#include <arena.h>
+#include <descriptor.h>
+#include <dynamic_message.h>
+
+#include <stubs/callback.h>
+#include <stubs/common.h>
+#include <stubs/logging.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <stubs/casts.h>
+#include <stubs/substitute.h>
+#include <stubs/stl_util.h>
+
+// Must be included last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+
+void DoNothing() {}
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+ MockErrorCollector() {}
+ ~MockErrorCollector() {}
+
+ std::string text_;
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, int line, int column,
+ const std::string& message) override {
+ strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+ message);
+ }
+};
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Test that generated code has proper descriptors:
+// Parse a descriptor directly (using google::protobuf::compiler::Importer) and
+// compare it to the one that was produced by generated code.
+TEST(GENERATED_DESCRIPTOR_TEST_NAME, IdenticalDescriptors) {
+ const FileDescriptor* generated_descriptor =
+ UNITTEST::TestAllTypes::descriptor()->file();
+
+ // Set up the Importer.
+ MockErrorCollector error_collector;
+ DiskSourceTree source_tree;
+ source_tree.MapPath("", TestUtil::TestSourceDir());
+ Importer importer(&source_tree, &error_collector);
+
+ // Import (parse) unittest.proto.
+ const FileDescriptor* parsed_descriptor =
+ importer.Import(TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH));
+ EXPECT_EQ("", error_collector.text_);
+ ASSERT_TRUE(parsed_descriptor != NULL);
+
+ // Test that descriptors are generated correctly by converting them to
+ // FileDescriptorProtos and comparing.
+ FileDescriptorProto generated_descriptor_proto, parsed_descriptor_proto;
+ generated_descriptor->CopyTo(&generated_descriptor_proto);
+ parsed_descriptor->CopyTo(&parsed_descriptor_proto);
+
+ EXPECT_EQ(parsed_descriptor_proto.DebugString(),
+ generated_descriptor_proto.DebugString());
+}
+
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// Test that generated code has proper descriptors:
+// Touch a descriptor generated from an enormous message to validate special
+// handling for descriptors exceeding the C++ standard's recommended minimum
+// limit for string literal size
+TEST(GENERATED_DESCRIPTOR_TEST_NAME, EnormousDescriptor) {
+ const Descriptor* generated_descriptor =
+ ::protobuf_unittest::TestEnormousDescriptor::descriptor();
+
+ EXPECT_TRUE(generated_descriptor != NULL);
+}
+#endif
+
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Defaults) {
+ // Check that all default values are set correctly in the initial message.
+ UNITTEST::TestAllTypes message;
+
+ TestUtil::ExpectClear(message);
+
+ // 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(),
+ &message.optionalgroup());
+ EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+ &message.optional_nested_message());
+ EXPECT_EQ(&UNITTEST::ForeignMessage::default_instance(),
+ &message.optional_foreign_message());
+ EXPECT_EQ(&UNITTEST_IMPORT::ImportMessage::default_instance(),
+ &message.optional_import_message());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, FloatingPointDefaults) {
+ const UNITTEST::TestExtremeDefaultValues& extreme_default =
+ UNITTEST::TestExtremeDefaultValues::default_instance();
+
+ EXPECT_EQ(0.0f, extreme_default.zero_float());
+ EXPECT_EQ(1.0f, extreme_default.one_float());
+ EXPECT_EQ(1.5f, extreme_default.small_float());
+ EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
+ EXPECT_EQ(-1.5f, extreme_default.negative_float());
+ EXPECT_EQ(2.0e8f, extreme_default.large_float());
+ EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(),
+ extreme_default.inf_double());
+ EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+ extreme_default.neg_inf_double());
+ EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
+ EXPECT_EQ(std::numeric_limits<float>::infinity(),
+ extreme_default.inf_float());
+ EXPECT_EQ(-std::numeric_limits<float>::infinity(),
+ extreme_default.neg_inf_float());
+ EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Trigraph) {
+ const UNITTEST::TestExtremeDefaultValues& extreme_default =
+ UNITTEST::TestExtremeDefaultValues::default_instance();
+
+ EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) {
+ const UNITTEST::TestExtremeDefaultValues& extreme_default =
+ UNITTEST::TestExtremeDefaultValues::default_instance();
+ EXPECT_EQ(std::numeric_limits<int32_t>::min(),
+ extreme_default.really_small_int32());
+ EXPECT_EQ(std::numeric_limits<int64_t>::min(),
+ extreme_default.really_small_int64());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Accessors) {
+ // Set every field to a unique value then go back and check all those
+ // values.
+ UNITTEST::TestAllTypes message;
+
+ TestUtil::SetAllFields(&message);
+ TestUtil::ExpectAllFieldsSet(message);
+
+ TestUtil::ModifyRepeatedFields(&message);
+ TestUtil::ExpectRepeatedFieldsModified(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, MutableStringDefault) {
+ // mutable_foo() for a string should return a string initialized to its
+ // default value.
+ UNITTEST::TestAllTypes message;
+
+ EXPECT_EQ("hello", *message.mutable_default_string());
+
+ // Note that the first time we call mutable_foo(), we get a newly-allocated
+ // string, but if we clear it and call it again, we get the same object again.
+ // We should verify that it has its default value in both cases.
+ message.set_default_string("blah");
+ message.Clear();
+
+ EXPECT_EQ("hello", *message.mutable_default_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, StringDefaults) {
+ UNITTEST::TestExtremeDefaultValues message;
+ // Check if '\000' can be used in default string value.
+ EXPECT_EQ(std::string("hel\000lo", 6), message.string_with_zero());
+ EXPECT_EQ(std::string("wor\000ld", 6), message.bytes_with_zero());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ReleaseString) {
+ // Check that release_foo() starts out NULL, and gives us a value
+ // that we can delete after it's been set.
+ UNITTEST::TestAllTypes message;
+
+ EXPECT_EQ(NULL, message.release_default_string());
+ EXPECT_FALSE(message.has_default_string());
+ EXPECT_EQ("hello", message.default_string());
+
+ message.set_default_string("blah");
+ EXPECT_TRUE(message.has_default_string());
+ std::unique_ptr<std::string> str(message.release_default_string());
+ EXPECT_FALSE(message.has_default_string());
+ ASSERT_TRUE(str != NULL);
+ EXPECT_EQ("blah", *str);
+
+ EXPECT_EQ(NULL, message.release_default_string());
+ EXPECT_FALSE(message.has_default_string());
+ EXPECT_EQ("hello", message.default_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ReleaseMessage) {
+ // Check that release_foo() starts out NULL, and gives us a value
+ // that we can delete after it's been set.
+ UNITTEST::TestAllTypes message;
+
+ EXPECT_EQ(NULL, message.release_optional_nested_message());
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ std::unique_ptr<UNITTEST::TestAllTypes::NestedMessage> nest(
+ message.release_optional_nested_message());
+ EXPECT_FALSE(message.has_optional_nested_message());
+ ASSERT_TRUE(nest != NULL);
+ EXPECT_EQ(1, nest->bb());
+
+ EXPECT_EQ(NULL, message.release_optional_nested_message());
+ EXPECT_FALSE(message.has_optional_nested_message());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedString) {
+ // Check that set_allocated_foo() works for strings.
+ UNITTEST::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_string());
+ const std::string kHello("hello");
+ message.set_optional_string(kHello);
+ EXPECT_TRUE(message.has_optional_string());
+
+ message.set_allocated_optional_string(NULL);
+ EXPECT_FALSE(message.has_optional_string());
+ EXPECT_EQ("", message.optional_string());
+
+ message.set_allocated_optional_string(new std::string(kHello));
+ EXPECT_TRUE(message.has_optional_string());
+ EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedMessage) {
+ // Check that set_allocated_foo() can be called in all cases.
+ UNITTEST::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ EXPECT_TRUE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+ EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+ &message.optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ UNITTEST::TestAllTypes::NestedMessage* nest =
+ message.release_optional_nested_message();
+ ASSERT_TRUE(nest != NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(nest);
+ EXPECT_TRUE(message.has_optional_nested_message());
+ EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Clear) {
+ // Set every field to a unique value, clear the message, then check that
+ // it is cleared.
+ UNITTEST::TestAllTypes message;
+
+ TestUtil::SetAllFields(&message);
+ message.Clear();
+ TestUtil::ExpectClear(message);
+
+ // Unlike with the defaults test, we do NOT expect that requesting embedded
+ // messages will return a pointer to the default instance. Instead, they
+ // should return the objects that were created when mutable_blah() was
+ // called.
+ EXPECT_NE(&UNITTEST::TestAllTypes::OptionalGroup::default_instance(),
+ &message.optionalgroup());
+ EXPECT_NE(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+ &message.optional_nested_message());
+ EXPECT_NE(&UNITTEST::ForeignMessage::default_instance(),
+ &message.optional_foreign_message());
+ EXPECT_NE(&UNITTEST_IMPORT::ImportMessage::default_instance(),
+ &message.optional_import_message());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, EmbeddedNullsInBytesCharStar) {
+ UNITTEST::TestAllTypes message;
+
+ const char* value = "\0lalala\0\0";
+ message.set_optional_bytes(value, 9);
+ ASSERT_EQ(9, message.optional_bytes().size());
+ EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9));
+
+ message.add_repeated_bytes(value, 9);
+ ASSERT_EQ(9, message.repeated_bytes(0).size());
+ EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ClearOneField) {
+ // Set every field to a unique value, then clear one value and insure that
+ // only that one value is cleared.
+ UNITTEST::TestAllTypes message;
+
+ TestUtil::SetAllFields(&message);
+ int64_t original_value = message.optional_int64();
+
+ // Clear the field and make sure it shows up as cleared.
+ message.clear_optional_int64();
+ EXPECT_FALSE(message.has_optional_int64());
+ EXPECT_EQ(0, message.optional_int64());
+
+ // Other adjacent fields should not be cleared.
+ EXPECT_TRUE(message.has_optional_int32());
+ EXPECT_TRUE(message.has_optional_uint32());
+
+ // Make sure if we set it again, then all fields are set.
+ message.set_optional_int64(original_value);
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, StringCharStarLength) {
+ // Verify that we can use a char*,length to set one of the string fields.
+ UNITTEST::TestAllTypes message;
+ message.set_optional_string("abcdef", 3);
+ EXPECT_EQ("abc", message.optional_string());
+
+ // Verify that we can use a char*,length to add to a repeated string field.
+ message.add_repeated_string("abcdef", 3);
+ EXPECT_EQ(1, message.repeated_string_size());
+ EXPECT_EQ("abc", message.repeated_string(0));
+
+ // Verify that we can use a char*,length to set a repeated string field.
+ message.set_repeated_string(0, "wxyz", 2);
+ EXPECT_EQ("wx", message.repeated_string(0));
+}
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyFrom) {
+ UNITTEST::TestAllTypes message1, message2;
+
+ TestUtil::SetAllFields(&message1);
+ message2.CopyFrom(message1);
+ TestUtil::ExpectAllFieldsSet(message2);
+
+ // Copying from self should be a no-op.
+ message2.CopyFrom(message2);
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithEmpty) {
+ UNITTEST::TestAllTypes message1, message2;
+ TestUtil::SetAllFields(&message1);
+
+ TestUtil::ExpectAllFieldsSet(message1);
+ TestUtil::ExpectClear(message2);
+ message1.Swap(&message2);
+ TestUtil::ExpectAllFieldsSet(message2);
+ TestUtil::ExpectClear(message1);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithSelf) {
+ UNITTEST::TestAllTypes message;
+ TestUtil::SetAllFields(&message);
+ TestUtil::ExpectAllFieldsSet(message);
+ message.Swap(&message);
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) {
+ UNITTEST::TestAllTypes message1, message2;
+
+ message1.set_optional_int32(123);
+ message1.set_optional_string("abc");
+ message1.mutable_optional_nested_message()->set_bb(1);
+ message1.set_optional_nested_enum(UNITTEST::TestAllTypes::FOO);
+ message1.add_repeated_int32(1);
+ message1.add_repeated_int32(2);
+ message1.add_repeated_string("a");
+ message1.add_repeated_string("b");
+ message1.add_repeated_nested_message()->set_bb(7);
+ message1.add_repeated_nested_message()->set_bb(8);
+ message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::FOO);
+ message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAR);
+
+ message2.set_optional_int32(456);
+ message2.set_optional_string("def");
+ message2.mutable_optional_nested_message()->set_bb(2);
+ message2.set_optional_nested_enum(UNITTEST::TestAllTypes::BAR);
+ message2.add_repeated_int32(3);
+ message2.add_repeated_string("c");
+ message2.add_repeated_nested_message()->set_bb(9);
+ message2.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ);
+
+ message1.Swap(&message2);
+
+ EXPECT_EQ(456, message1.optional_int32());
+ EXPECT_EQ("def", message1.optional_string());
+ EXPECT_EQ(2, message1.optional_nested_message().bb());
+ EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message1.optional_nested_enum());
+ ASSERT_EQ(1, message1.repeated_int32_size());
+ EXPECT_EQ(3, message1.repeated_int32(0));
+ ASSERT_EQ(1, message1.repeated_string_size());
+ EXPECT_EQ("c", message1.repeated_string(0));
+ ASSERT_EQ(1, message1.repeated_nested_message_size());
+ EXPECT_EQ(9, message1.repeated_nested_message(0).bb());
+ ASSERT_EQ(1, message1.repeated_nested_enum_size());
+ EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message1.repeated_nested_enum(0));
+
+ EXPECT_EQ(123, message2.optional_int32());
+ EXPECT_EQ("abc", message2.optional_string());
+ EXPECT_EQ(1, message2.optional_nested_message().bb());
+ EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.optional_nested_enum());
+ ASSERT_EQ(2, message2.repeated_int32_size());
+ EXPECT_EQ(1, message2.repeated_int32(0));
+ EXPECT_EQ(2, message2.repeated_int32(1));
+ ASSERT_EQ(2, message2.repeated_string_size());
+ EXPECT_EQ("a", message2.repeated_string(0));
+ EXPECT_EQ("b", message2.repeated_string(1));
+ ASSERT_EQ(2, message2.repeated_nested_message_size());
+ EXPECT_EQ(7, message2.repeated_nested_message(0).bb());
+ EXPECT_EQ(8, message2.repeated_nested_message(1).bb());
+ ASSERT_EQ(2, message2.repeated_nested_enum_size());
+ EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.repeated_nested_enum(0));
+ EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message2.repeated_nested_enum(1));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ADLSwap) {
+ UNITTEST::TestAllTypes message1, message2;
+ TestUtil::SetAllFields(&message1);
+
+ // Note the address of one of the repeated fields, to verify it was swapped
+ // rather than copied.
+ const int32_t* addr = &message1.repeated_int32().Get(0);
+
+ using std::swap;
+ swap(message1, message2);
+
+ TestUtil::ExpectAllFieldsSet(message2);
+ TestUtil::ExpectClear(message1);
+
+#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ EXPECT_NE(addr, &message2.repeated_int32().Get(0));
+ EXPECT_EQ(*addr, message2.repeated_int32().Get(0));
+#else
+ EXPECT_EQ(addr, &message2.repeated_int32().Get(0));
+#endif
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructor) {
+ // All set.
+ {
+ UNITTEST::TestAllTypes message1;
+ TestUtil::SetAllFields(&message1);
+
+ UNITTEST::TestAllTypes message2(message1);
+ TestUtil::ExpectAllFieldsSet(message2);
+ }
+
+ // None set.
+ {
+ UNITTEST::TestAllTypes message1;
+ UNITTEST::TestAllTypes message2(message1);
+
+ EXPECT_FALSE(message1.has_optional_string());
+ EXPECT_FALSE(message2.has_optional_string());
+ EXPECT_EQ(message1.optional_string(), message2.optional_string());
+
+ EXPECT_FALSE(message1.has_optional_bytes());
+ EXPECT_FALSE(message2.has_optional_bytes());
+ EXPECT_EQ(message1.optional_bytes(), message2.optional_bytes());
+
+ EXPECT_FALSE(message1.has_optional_nested_message());
+ EXPECT_FALSE(message2.has_optional_nested_message());
+ EXPECT_EQ(&message1.optional_nested_message(),
+ &message2.optional_nested_message());
+
+ EXPECT_FALSE(message1.has_optional_foreign_message());
+ EXPECT_FALSE(message2.has_optional_foreign_message());
+ EXPECT_EQ(&message1.optional_foreign_message(),
+ &message2.optional_foreign_message());
+
+ EXPECT_FALSE(message1.has_optional_import_message());
+ EXPECT_FALSE(message2.has_optional_import_message());
+ EXPECT_EQ(&message1.optional_import_message(),
+ &message2.optional_import_message());
+
+ EXPECT_FALSE(message1.has_optional_public_import_message());
+ EXPECT_FALSE(message2.has_optional_public_import_message());
+ EXPECT_EQ(&message1.optional_public_import_message(),
+ &message2.optional_public_import_message());
+
+ EXPECT_FALSE(message1.has_optional_lazy_message());
+ EXPECT_FALSE(message2.has_optional_lazy_message());
+ EXPECT_EQ(&message1.optional_lazy_message(),
+ &message2.optional_lazy_message());
+ }
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructorWithArenas) {
+ Arena arena;
+ UNITTEST::TestAllTypes* message1 =
+ Arena::CreateMessage<UNITTEST::TestAllTypes>(&arena);
+ TestUtil::SetAllFields(message1);
+
+ UNITTEST::TestAllTypes message2_stack(*message1);
+ TestUtil::ExpectAllFieldsSet(message2_stack);
+
+ std::unique_ptr<UNITTEST::TestAllTypes> message2_heap(
+ new UNITTEST::TestAllTypes(*message1));
+ TestUtil::ExpectAllFieldsSet(*message2_heap);
+
+ arena.Reset();
+
+ // Verify that the copies are still intact.
+ TestUtil::ExpectAllFieldsSet(message2_stack);
+ TestUtil::ExpectAllFieldsSet(*message2_heap);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyAssignmentOperator) {
+ UNITTEST::TestAllTypes message1;
+ TestUtil::SetAllFields(&message1);
+
+ UNITTEST::TestAllTypes message2;
+ message2 = message1;
+ TestUtil::ExpectAllFieldsSet(message2);
+
+ // Make sure that self-assignment does something sane.
+ message2.operator=(message2);
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || PROTOBUF_RTTI
+TEST(GENERATED_MESSAGE_TEST_NAME, UpcastCopyFrom) {
+ // Test the CopyFrom method that takes in the generic const Message&
+ // parameter.
+ UNITTEST::TestAllTypes message1, message2;
+
+ TestUtil::SetAllFields(&message1);
+
+ const Message* source = implicit_cast<const Message*>(&message1);
+ message2.CopyFrom(*source);
+
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+#endif
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, DynamicMessageCopyFrom) {
+ // Test copying from a DynamicMessage, which must fall back to using
+ // reflection.
+ UNITTEST::TestAllTypes message2;
+
+ // Construct a new version of the dynamic message via the factory.
+ DynamicMessageFactory factory;
+ std::unique_ptr<Message> message1;
+ message1.reset(factory.GetPrototype(
+ UNITTEST::TestAllTypes::descriptor())->New());
+
+ TestUtil::ReflectionTester reflection_tester(
+ UNITTEST::TestAllTypes::descriptor());
+ reflection_tester.SetAllFieldsViaReflection(message1.get());
+
+ message2.CopyFrom(*message1);
+
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, NonEmptyMergeFrom) {
+ // Test merging with a non-empty message. Code is a modified form
+ // of that found in net/proto2/internal/reflection_ops_unittest.cc.
+ UNITTEST::TestAllTypes message1, message2;
+
+ TestUtil::SetAllFields(&message1);
+
+ // This field will test merging into an empty spot.
+ message2.set_optional_int32(message1.optional_int32());
+ message1.clear_optional_int32();
+
+ // This tests overwriting.
+ message2.set_optional_string(message1.optional_string());
+ message1.set_optional_string("something else");
+
+ // This tests concatenating.
+ message2.add_repeated_int32(message1.repeated_int32(1));
+ int32_t i = message1.repeated_int32(0);
+ message1.clear_repeated_int32();
+ message1.add_repeated_int32(i);
+
+ message1.MergeFrom(message2);
+
+ TestUtil::ExpectAllFieldsSet(message1);
+}
+
+
+// Test the generated SerializeWithCachedSizesToArray(),
+TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToArray) {
+ UNITTEST::TestAllTypes message1, message2;
+ std::string data;
+ TestUtil::SetAllFields(&message1);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToArray) {
+ UNITTEST::TestPackedTypes packed_message1, packed_message2;
+ std::string packed_data;
+ TestUtil::SetPackedFields(&packed_message1);
+ int packed_size = packed_message1.ByteSizeLong();
+ packed_data.resize(packed_size);
+ uint8_t* start =
+ reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&packed_data));
+ uint8_t* end = packed_message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(packed_size, end - start);
+ EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
+ TestUtil::ExpectPackedFieldsSet(packed_message2);
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToStream) {
+ UNITTEST::TestAllTypes message1, message2;
+ TestUtil::SetAllFields(&message1);
+ int size = message1.ByteSizeLong();
+ std::string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToStream) {
+ UNITTEST::TestPackedTypes message1, message2;
+ TestUtil::SetPackedFields(&message1);
+ int size = message1.ByteSizeLong();
+ std::string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ TestUtil::ExpectPackedFieldsSet(message2);
+}
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Required) {
+ // Test that IsInitialized() returns false if required fields are missing.
+ UNITTEST::TestRequired message;
+
+ EXPECT_FALSE(message.IsInitialized());
+ message.set_a(1);
+ EXPECT_FALSE(message.IsInitialized());
+ message.set_b(2);
+ EXPECT_FALSE(message.IsInitialized());
+ message.set_c(3);
+ EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, RequiredForeign) {
+ // Test that IsInitialized() returns false if required fields in nested
+ // messages are missing.
+ UNITTEST::TestRequiredForeign message;
+
+ EXPECT_TRUE(message.IsInitialized());
+
+ message.mutable_optional_message();
+ EXPECT_FALSE(message.IsInitialized());
+
+ message.mutable_optional_message()->set_a(1);
+ message.mutable_optional_message()->set_b(2);
+ message.mutable_optional_message()->set_c(3);
+ EXPECT_TRUE(message.IsInitialized());
+
+ message.add_repeated_message();
+ EXPECT_FALSE(message.IsInitialized());
+
+ message.mutable_repeated_message(0)->set_a(1);
+ message.mutable_repeated_message(0)->set_b(2);
+ message.mutable_repeated_message(0)->set_c(3);
+ EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ForeignNested) {
+ // Test that TestAllTypes::NestedMessage can be embedded directly into
+ // another message.
+ UNITTEST::TestForeignNested message;
+
+ // If this compiles and runs without crashing, it must work. We have
+ // nothing more to test.
+ UNITTEST::TestAllTypes::NestedMessage* nested =
+ message.mutable_foreign_nested();
+ nested->set_bb(1);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ReallyLargeTagNumber) {
+ // Test that really large tag numbers don't break anything.
+ UNITTEST::TestReallyLargeTagNumber message1, message2;
+ std::string data;
+
+ // For the most part, if this compiles and runs then we're probably good.
+ // (The most likely cause for failure would be if something were attempting
+ // to allocate a lookup table of some sort using tag numbers as the index.)
+ // We'll try serializing just for fun.
+ message1.set_a(1234);
+ message1.set_bb(5678);
+ message1.SerializeToString(&data);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(1234, message2.a());
+ EXPECT_EQ(5678, message2.bb());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, MutualRecursion) {
+ // Test that mutually-recursive message types work.
+ UNITTEST::TestMutualRecursionA message;
+ UNITTEST::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a();
+ UNITTEST::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a();
+
+ // Again, if the above compiles and runs, that's all we really have to
+ // test, but just for run we'll check that the system didn't somehow come
+ // up with a pointer loop...
+ EXPECT_NE(&message, nested);
+ EXPECT_NE(&message, nested2);
+ EXPECT_NE(nested, nested2);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CamelCaseFieldNames) {
+ // This test is mainly checking that the following compiles, which verifies
+ // that the field names were coerced to lower-case.
+ //
+ // Protocol buffers standard style is to use lowercase-with-underscores for
+ // field names. Some old proto1 .protos unfortunately used camel-case field
+ // names. In proto1, these names were forced to lower-case. So, we do the
+ // same thing in proto2.
+
+ UNITTEST::TestCamelCaseFieldNames message;
+
+ message.set_primitivefield(2);
+ message.set_stringfield("foo");
+ message.set_enumfield(UNITTEST::FOREIGN_FOO);
+ message.mutable_messagefield()->set_c(6);
+
+ message.add_repeatedprimitivefield(8);
+ message.add_repeatedstringfield("qux");
+ message.add_repeatedenumfield(UNITTEST::FOREIGN_BAR);
+ message.add_repeatedmessagefield()->set_c(15);
+
+ EXPECT_EQ(2, message.primitivefield());
+ EXPECT_EQ("foo", message.stringfield());
+ EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.enumfield());
+ EXPECT_EQ(6, message.messagefield().c());
+
+ EXPECT_EQ(8, message.repeatedprimitivefield(0));
+ EXPECT_EQ("qux", message.repeatedstringfield(0));
+ EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeatedenumfield(0));
+ EXPECT_EQ(15, message.repeatedmessagefield(0).c());
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestOptimizedForSize) {
+ // We rely on the tests in reflection_ops_unittest and wire_format_unittest
+ // to really test that reflection-based methods work. Here we are mostly
+ // just making sure that TestOptimizedForSize actually builds and seems to
+ // function.
+
+ UNITTEST::TestOptimizedForSize message, message2;
+ message.set_i(1);
+ message.mutable_msg()->set_c(2);
+ message2.CopyFrom(message);
+ EXPECT_EQ(1, message2.i());
+ EXPECT_EQ(2, message2.msg().c());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestEmbedOptimizedForSize) {
+ // Verifies that something optimized for speed can contain something optimized
+ // for size.
+
+ UNITTEST::TestEmbedOptimizedForSize message, message2;
+ message.mutable_optional_message()->set_i(1);
+ message.add_repeated_message()->mutable_msg()->set_c(2);
+ std::string data;
+ message.SerializeToString(&data);
+ ASSERT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(1, message2.optional_message().i());
+ EXPECT_EQ(2, message2.repeated_message(0).msg().c());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestSpaceUsed) {
+ UNITTEST::TestAllTypes message1;
+ // sizeof provides a lower bound on SpaceUsedLong().
+ EXPECT_LE(sizeof(UNITTEST::TestAllTypes), message1.SpaceUsedLong());
+ const size_t empty_message_size = message1.SpaceUsedLong();
+
+ // Setting primitive types shouldn't affect the space used.
+ message1.set_optional_int32(123);
+ message1.set_optional_int64(12345);
+ message1.set_optional_uint32(123);
+ message1.set_optional_uint64(12345);
+ EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
+
+ // On some STL implementations, setting the string to a small value should
+ // only increase SpaceUsedLong() by the size of a string object, though this
+ // is not true everywhere.
+ message1.set_optional_string("abc");
+ EXPECT_LE(empty_message_size + message1.optional_string().size(),
+ message1.SpaceUsedLong());
+
+ // Setting a string to a value larger than the string object itself should
+ // increase SpaceUsedLong(), because it cannot store the value internally.
+ message1.set_optional_string(std::string(sizeof(std::string) + 1, 'x'));
+ int min_expected_increase = message1.optional_string().capacity();
+ EXPECT_LE(empty_message_size + min_expected_increase,
+ message1.SpaceUsedLong());
+
+ size_t previous_size = message1.SpaceUsedLong();
+ // Adding an optional message should increase the size by the size of the
+ // nested message type. NestedMessage is simple enough (1 int field) that it
+ // is equal to sizeof(NestedMessage)
+ message1.mutable_optional_nested_message();
+ ASSERT_EQ(sizeof(UNITTEST::TestAllTypes::NestedMessage),
+ message1.optional_nested_message().SpaceUsedLong());
+ EXPECT_EQ(previous_size +
+ sizeof(UNITTEST::TestAllTypes::NestedMessage),
+ message1.SpaceUsedLong());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestOneofSpaceUsed) {
+ UNITTEST::TestOneof2 message1;
+ EXPECT_LE(sizeof(UNITTEST::TestOneof2), message1.SpaceUsedLong());
+
+ const size_t empty_message_size = message1.SpaceUsedLong();
+ // Setting primitive types shouldn't affect the space used.
+ message1.set_foo_int(123);
+ message1.set_bar_int(12345);
+ EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
+
+ // Setting a string in oneof to a small value should only increase
+ // SpaceUsedLong() by the size of a string object.
+ message1.set_foo_string("abc");
+ EXPECT_LE(empty_message_size + sizeof(std::string), message1.SpaceUsedLong());
+
+ // Setting a string in oneof to a value larger than the string object itself
+ // should increase SpaceUsedLong(), because it cannot store the value
+ // internally.
+ message1.set_foo_string(std::string(sizeof(std::string) + 1, 'x'));
+ int min_expected_increase =
+ message1.foo_string().capacity() + sizeof(std::string);
+ EXPECT_LE(empty_message_size + min_expected_increase,
+ message1.SpaceUsedLong());
+
+ // Setting a message in oneof should delete the other fields and increase the
+ // size by the size of the nested message type. NestedMessage is simple enough
+ // that it is equal to sizeof(NestedMessage). It may be backed by LazyField,
+ // increasing space used by LazyField and backing Cord.
+ message1.mutable_foo_message();
+ ASSERT_EQ(sizeof(UNITTEST::TestOneof2::NestedMessage),
+ message1.foo_message().SpaceUsedLong());
+ EXPECT_LE(empty_message_size + sizeof(UNITTEST::TestOneof2::NestedMessage),
+ message1.SpaceUsedLong());
+}
+
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, FieldConstantValues) {
+ UNITTEST::TestRequired message;
+ EXPECT_EQ(UNITTEST::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalInt32FieldNumber, 1);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalgroupFieldNumber, 16);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedInt32FieldNumber, 31);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedgroupFieldNumber, 46);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
+ EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ExtensionConstantValues) {
+ EXPECT_EQ(UNITTEST::TestRequired::kSingleFieldNumber, 1000);
+ EXPECT_EQ(UNITTEST::TestRequired::kMultiFieldNumber, 1001);
+ EXPECT_EQ(UNITTEST::kOptionalInt32ExtensionFieldNumber, 1);
+ EXPECT_EQ(UNITTEST::kOptionalgroupExtensionFieldNumber, 16);
+ EXPECT_EQ(UNITTEST::kOptionalNestedMessageExtensionFieldNumber, 18);
+ EXPECT_EQ(UNITTEST::kOptionalNestedEnumExtensionFieldNumber, 21);
+ EXPECT_EQ(UNITTEST::kRepeatedInt32ExtensionFieldNumber, 31);
+ EXPECT_EQ(UNITTEST::kRepeatedgroupExtensionFieldNumber, 46);
+ EXPECT_EQ(UNITTEST::kRepeatedNestedMessageExtensionFieldNumber, 48);
+ EXPECT_EQ(UNITTEST::kRepeatedNestedEnumExtensionFieldNumber, 51);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ParseFromTruncated) {
+ const std::string long_string = std::string(128, 'q');
+ FileDescriptorProto p;
+ p.add_extension()->set_name(long_string);
+ const std::string msg = p.SerializeAsString();
+ int successful_count = 0;
+ for (int i = 0; i <= msg.size(); i++) {
+ if (p.ParseFromArray(msg.c_str(), i)) {
+ ++successful_count;
+ }
+ }
+ // We don't really care about how often we succeeded.
+ // As long as we didn't crash, we're happy.
+ EXPECT_GE(successful_count, 1);
+}
+
+// ===================================================================
+
+TEST(GENERATED_ENUM_TEST_NAME, EnumValuesAsSwitchCases) {
+ // Test that our nested enum values can be used as switch cases. This test
+ // doesn't actually do anything, the proof that it works is that it
+ // compiles.
+ int i =0;
+ UNITTEST::TestAllTypes::NestedEnum a = UNITTEST::TestAllTypes::BAR;
+ switch (a) {
+ case UNITTEST::TestAllTypes::FOO:
+ i = 1;
+ break;
+ case UNITTEST::TestAllTypes::BAR:
+ i = 2;
+ break;
+ case UNITTEST::TestAllTypes::BAZ:
+ i = 3;
+ break;
+ case UNITTEST::TestAllTypes::NEG:
+ i = -1;
+ break;
+ // no default case: We want to make sure the compiler recognizes that
+ // all cases are covered. (GCC warns if you do not cover all cases of
+ // an enum in a switch.)
+ }
+
+ // Token check just for fun.
+ EXPECT_EQ(2, i);
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, IsValidValue) {
+ // Test enum IsValidValue.
+ EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(1));
+ EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(2));
+ EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(3));
+
+ EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(0));
+ EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(4));
+
+ // Make sure it also works when there are dups.
+ EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(1));
+ EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(2));
+ EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(3));
+
+ EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(0));
+ EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(4));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, MinAndMax) {
+ EXPECT_EQ(UNITTEST::TestAllTypes::NEG,
+ UNITTEST::TestAllTypes::NestedEnum_MIN);
+ EXPECT_EQ(UNITTEST::TestAllTypes::BAZ,
+ UNITTEST::TestAllTypes::NestedEnum_MAX);
+ EXPECT_EQ(4, UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+ EXPECT_EQ(UNITTEST::FOREIGN_FOO, UNITTEST::ForeignEnum_MIN);
+ EXPECT_EQ(UNITTEST::FOREIGN_BAZ, UNITTEST::ForeignEnum_MAX);
+ EXPECT_EQ(7, UNITTEST::ForeignEnum_ARRAYSIZE);
+
+ EXPECT_EQ(1, UNITTEST::TestEnumWithDupValue_MIN);
+ EXPECT_EQ(3, UNITTEST::TestEnumWithDupValue_MAX);
+ EXPECT_EQ(4, UNITTEST::TestEnumWithDupValue_ARRAYSIZE);
+
+ EXPECT_EQ(UNITTEST::SPARSE_E, UNITTEST::TestSparseEnum_MIN);
+ EXPECT_EQ(UNITTEST::SPARSE_C, UNITTEST::TestSparseEnum_MAX);
+ EXPECT_EQ(12589235, UNITTEST::TestSparseEnum_ARRAYSIZE);
+
+ // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
+ void* null_pointer = 0; // NULL may be integer-type, not pointer-type.
+ EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MIN);
+ EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MAX);
+ EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+ EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MIN);
+ EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MAX);
+ EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_ARRAYSIZE);
+
+ // Make sure we can use _MIN and _MAX as switch cases.
+ switch (UNITTEST::SPARSE_A) {
+ case UNITTEST::TestSparseEnum_MIN:
+ case UNITTEST::TestSparseEnum_MAX:
+ break;
+ default:
+ break;
+ }
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_ENUM_TEST_NAME, Name) {
+ // "Names" in the presence of dup values map to the first alias.
+ EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO1));
+ EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO2));
+
+ EXPECT_EQ("SPARSE_A", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_A));
+ EXPECT_EQ("SPARSE_B", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_B));
+ EXPECT_EQ("SPARSE_C", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_C));
+ EXPECT_EQ("SPARSE_D", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_D));
+ EXPECT_EQ("SPARSE_E", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_E));
+ EXPECT_EQ("SPARSE_F", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_F));
+ EXPECT_EQ("SPARSE_G", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_G));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, Parse) {
+ UNITTEST::TestEnumWithDupValue dup_value = UNITTEST::FOO1;
+ EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO1", &dup_value));
+ EXPECT_EQ(UNITTEST::FOO1, dup_value);
+ EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO2", &dup_value));
+ EXPECT_EQ(UNITTEST::FOO2, dup_value);
+ EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_Parse("FOO", &dup_value));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, GetEnumDescriptor) {
+ EXPECT_EQ(UNITTEST::TestAllTypes::NestedEnum_descriptor(),
+ GetEnumDescriptor<UNITTEST::TestAllTypes::NestedEnum>());
+ EXPECT_EQ(UNITTEST::ForeignEnum_descriptor(),
+ GetEnumDescriptor<UNITTEST::ForeignEnum>());
+ EXPECT_EQ(UNITTEST::TestEnumWithDupValue_descriptor(),
+ GetEnumDescriptor<UNITTEST::TestEnumWithDupValue>());
+ EXPECT_EQ(UNITTEST::TestSparseEnum_descriptor(),
+ GetEnumDescriptor<UNITTEST::TestSparseEnum>());
+}
+
+enum NonProtoEnum {
+ kFoo = 1,
+};
+
+TEST(GENERATED_ENUM_TEST_NAME, IsProtoEnumTypeTrait) {
+ EXPECT_TRUE(is_proto_enum<UNITTEST::TestAllTypes::NestedEnum>::value);
+ EXPECT_TRUE(is_proto_enum<UNITTEST::ForeignEnum>::value);
+ EXPECT_TRUE(is_proto_enum<UNITTEST::TestEnumWithDupValue>::value);
+ EXPECT_TRUE(is_proto_enum<UNITTEST::TestSparseEnum>::value);
+
+ EXPECT_FALSE(is_proto_enum<int>::value);
+ EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value);
+}
+
+#endif // PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Support code for testing services.
+class GENERATED_SERVICE_TEST_NAME : public testing::Test {
+ protected:
+ class MockTestService : public UNITTEST::TestService {
+ public:
+ MockTestService()
+ : called_(false),
+ method_(""),
+ controller_(NULL),
+ request_(NULL),
+ response_(NULL),
+ done_(NULL) {}
+
+ ~MockTestService() {}
+
+ void Reset() { called_ = false; }
+
+ // implements TestService ----------------------------------------
+
+ void Foo(RpcController* controller, const UNITTEST::FooRequest* request,
+ UNITTEST::FooResponse* response, Closure* done) override {
+ ASSERT_FALSE(called_);
+ called_ = true;
+ method_ = "Foo";
+ controller_ = controller;
+ request_ = request;
+ response_ = response;
+ done_ = done;
+ }
+
+ void Bar(RpcController* controller, const UNITTEST::BarRequest* request,
+ UNITTEST::BarResponse* response, Closure* done) override {
+ ASSERT_FALSE(called_);
+ called_ = true;
+ method_ = "Bar";
+ controller_ = controller;
+ request_ = request;
+ response_ = response;
+ done_ = done;
+ }
+
+ // ---------------------------------------------------------------
+
+ bool called_;
+ std::string method_;
+ RpcController* controller_;
+ const Message* request_;
+ Message* response_;
+ Closure* done_;
+ };
+
+ class MockRpcChannel : public RpcChannel {
+ public:
+ MockRpcChannel()
+ : called_(false),
+ method_(NULL),
+ controller_(NULL),
+ request_(NULL),
+ response_(NULL),
+ done_(NULL),
+ destroyed_(NULL) {}
+
+ ~MockRpcChannel() {
+ if (destroyed_ != NULL) *destroyed_ = true;
+ }
+
+ void Reset() { called_ = false; }
+
+ // implements TestService ----------------------------------------
+
+ void CallMethod(const MethodDescriptor* method, RpcController* controller,
+ const Message* request, Message* response,
+ Closure* done) override {
+ ASSERT_FALSE(called_);
+ called_ = true;
+ method_ = method;
+ controller_ = controller;
+ request_ = request;
+ response_ = response;
+ done_ = done;
+ }
+
+ // ---------------------------------------------------------------
+
+ bool called_;
+ const MethodDescriptor* method_;
+ RpcController* controller_;
+ const Message* request_;
+ Message* response_;
+ Closure* done_;
+ bool* destroyed_;
+ };
+
+ class MockController : public RpcController {
+ public:
+ void Reset() override {
+ ADD_FAILURE() << "Reset() not expected during this test.";
+ }
+ bool Failed() const override {
+ ADD_FAILURE() << "Failed() not expected during this test.";
+ return false;
+ }
+ std::string ErrorText() const override {
+ ADD_FAILURE() << "ErrorText() not expected during this test.";
+ return "";
+ }
+ void StartCancel() override {
+ ADD_FAILURE() << "StartCancel() not expected during this test.";
+ }
+ void SetFailed(const std::string& reason) override {
+ ADD_FAILURE() << "SetFailed() not expected during this test.";
+ }
+ bool IsCanceled() const override {
+ ADD_FAILURE() << "IsCanceled() not expected during this test.";
+ return false;
+ }
+ void NotifyOnCancel(Closure* callback) override {
+ ADD_FAILURE() << "NotifyOnCancel() not expected during this test.";
+ }
+ };
+
+ GENERATED_SERVICE_TEST_NAME()
+ : descriptor_(UNITTEST::TestService::descriptor()),
+ foo_(descriptor_->FindMethodByName("Foo")),
+ bar_(descriptor_->FindMethodByName("Bar")),
+ stub_(&mock_channel_),
+ done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {}
+
+ void SetUp() override {
+ ASSERT_TRUE(foo_ != NULL);
+ ASSERT_TRUE(bar_ != NULL);
+ }
+
+ const ServiceDescriptor* descriptor_;
+ const MethodDescriptor* foo_;
+ const MethodDescriptor* bar_;
+
+ MockTestService mock_service_;
+ MockController mock_controller_;
+
+ MockRpcChannel mock_channel_;
+ UNITTEST::TestService::Stub stub_;
+
+ // Just so we don't have to re-define these with every test.
+ UNITTEST::FooRequest foo_request_;
+ UNITTEST::FooResponse foo_response_;
+ UNITTEST::BarRequest bar_request_;
+ UNITTEST::BarResponse bar_response_;
+ std::unique_ptr<Closure> done_;
+};
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetDescriptor) {
+ // Test that GetDescriptor() works.
+
+ EXPECT_EQ(descriptor_, mock_service_.GetDescriptor());
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetChannel) {
+ EXPECT_EQ(&mock_channel_, stub_.channel());
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, OwnsChannel) {
+ MockRpcChannel* channel = new MockRpcChannel;
+ bool destroyed = false;
+ channel->destroyed_ = &destroyed;
+
+ {
+ UNITTEST::TestService::Stub owning_stub(channel,
+ Service::STUB_OWNS_CHANNEL);
+ EXPECT_FALSE(destroyed);
+ }
+
+ EXPECT_TRUE(destroyed);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethod) {
+ // Test that CallMethod() works.
+
+ // Call Foo() via CallMethod().
+ mock_service_.CallMethod(foo_, &mock_controller_,
+ &foo_request_, &foo_response_, done_.get());
+
+ ASSERT_TRUE(mock_service_.called_);
+
+ EXPECT_EQ("Foo" , mock_service_.method_ );
+ EXPECT_EQ(&mock_controller_, mock_service_.controller_);
+ EXPECT_EQ(&foo_request_ , mock_service_.request_ );
+ EXPECT_EQ(&foo_response_ , mock_service_.response_ );
+ EXPECT_EQ(done_.get() , mock_service_.done_ );
+
+ // Try again, but call Bar() instead.
+ mock_service_.Reset();
+ mock_service_.CallMethod(bar_, &mock_controller_,
+ &bar_request_, &bar_response_, done_.get());
+
+ ASSERT_TRUE(mock_service_.called_);
+ EXPECT_EQ("Bar", mock_service_.method_);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethodTypeFailure) {
+ // Verify death if we call Foo() with Bar's message types.
+
+#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet
+ EXPECT_DEBUG_DEATH(
+ mock_service_.CallMethod(foo_, &mock_controller_,
+ &foo_request_, &bar_response_, done_.get()),
+ "dynamic_cast");
+
+ mock_service_.Reset();
+ EXPECT_DEBUG_DEATH(
+ mock_service_.CallMethod(foo_, &mock_controller_,
+ &bar_request_, &foo_response_, done_.get()),
+ "dynamic_cast");
+#endif // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetPrototypes) {
+ // Test Get{Request,Response}Prototype() methods.
+
+ EXPECT_EQ(&UNITTEST::FooRequest::default_instance(),
+ &mock_service_.GetRequestPrototype(foo_));
+ EXPECT_EQ(&UNITTEST::BarRequest::default_instance(),
+ &mock_service_.GetRequestPrototype(bar_));
+
+ EXPECT_EQ(&UNITTEST::FooResponse::default_instance(),
+ &mock_service_.GetResponsePrototype(foo_));
+ EXPECT_EQ(&UNITTEST::BarResponse::default_instance(),
+ &mock_service_.GetResponsePrototype(bar_));
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, Stub) {
+ // Test that the stub class works.
+
+ // Call Foo() via the stub.
+ stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get());
+
+ ASSERT_TRUE(mock_channel_.called_);
+
+ EXPECT_EQ(foo_ , mock_channel_.method_ );
+ EXPECT_EQ(&mock_controller_, mock_channel_.controller_);
+ EXPECT_EQ(&foo_request_ , mock_channel_.request_ );
+ EXPECT_EQ(&foo_response_ , mock_channel_.response_ );
+ EXPECT_EQ(done_.get() , mock_channel_.done_ );
+
+ // Call Bar() via the stub.
+ mock_channel_.Reset();
+ stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get());
+
+ ASSERT_TRUE(mock_channel_.called_);
+ EXPECT_EQ(bar_, mock_channel_.method_);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, NotImplemented) {
+ // Test that failing to implement a method of a service causes it to fail
+ // with a "not implemented" error message.
+
+ // A service which doesn't implement any methods.
+ class UnimplementedService : public UNITTEST::TestService {
+ public:
+ UnimplementedService() {}
+ };
+
+ UnimplementedService unimplemented_service;
+
+ // And a controller which expects to get a "not implemented" error.
+ class ExpectUnimplementedController : public MockController {
+ public:
+ ExpectUnimplementedController() : called_(false) {}
+
+ void SetFailed(const std::string& reason) override {
+ EXPECT_FALSE(called_);
+ called_ = true;
+ EXPECT_EQ("Method Foo() not implemented.", reason);
+ }
+
+ bool called_;
+ };
+
+ ExpectUnimplementedController controller;
+
+ // Call Foo.
+ unimplemented_service.Foo(&controller, &foo_request_, &foo_response_,
+ done_.get());
+
+ EXPECT_TRUE(controller.called_);
+}
+
+// ===================================================================
+
+class OneofTest : public testing::Test {
+ protected:
+ void SetUp() override {}
+
+ void ExpectEnumCasesWork(const UNITTEST::TestOneof2 &message) {
+ switch (message.foo_case()) {
+ case UNITTEST::TestOneof2::kFooInt:
+ EXPECT_TRUE(message.has_foo_int());
+ break;
+ case UNITTEST::TestOneof2::kFooString:
+ EXPECT_TRUE(message.has_foo_string());
+ break;
+ case UNITTEST::TestOneof2::kFooCord:
+ EXPECT_TRUE(message.has_foo_cord());
+ break;
+ case UNITTEST::TestOneof2::kFooStringPiece:
+ EXPECT_TRUE(message.has_foo_string_piece());
+ break;
+ case UNITTEST::TestOneof2::kFooBytes:
+ EXPECT_TRUE(message.has_foo_bytes());
+ break;
+ case UNITTEST::TestOneof2::kFooEnum:
+ EXPECT_TRUE(message.has_foo_enum());
+ break;
+ case UNITTEST::TestOneof2::kFooMessage:
+ EXPECT_TRUE(message.has_foo_message());
+ break;
+ case UNITTEST::TestOneof2::kFoogroup:
+ EXPECT_TRUE(message.has_foogroup());
+ break;
+ case UNITTEST::TestOneof2::kFooLazyMessage:
+ EXPECT_TRUE(message.has_foo_lazy_message());
+ break;
+ case UNITTEST::TestOneof2::FOO_NOT_SET:
+ break;
+ }
+ }
+};
+
+TEST_F(OneofTest, SettingOneFieldClearsOthers) {
+ UNITTEST::TestOneof2 message;
+
+ message.set_foo_int(123);
+ EXPECT_TRUE(message.has_foo_int());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+ message.set_foo_string("foo");
+ EXPECT_TRUE(message.has_foo_string());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+ message.set_foo_bytes("qux");
+ EXPECT_TRUE(message.has_foo_bytes());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+ message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ EXPECT_TRUE(message.has_foo_enum());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+ message.mutable_foo_message()->set_qux_int(234);
+ EXPECT_TRUE(message.has_foo_message());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+ message.mutable_foogroup()->set_a(345);
+ EXPECT_TRUE(message.has_foogroup());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+ // we repeat this because we didn't test if this properly clears other fields
+ // at the beginning.
+ message.set_foo_int(123);
+ EXPECT_TRUE(message.has_foo_int());
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+}
+
+TEST_F(OneofTest, EnumCases) {
+ UNITTEST::TestOneof2 message;
+
+ message.set_foo_int(123);
+ ExpectEnumCasesWork(message);
+ message.set_foo_string("foo");
+ ExpectEnumCasesWork(message);
+ message.set_foo_bytes("qux");
+ ExpectEnumCasesWork(message);
+ message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ ExpectEnumCasesWork(message);
+ message.mutable_foo_message()->set_qux_int(234);
+ ExpectEnumCasesWork(message);
+ message.mutable_foogroup()->set_a(345);
+ ExpectEnumCasesWork(message);
+}
+
+TEST_F(OneofTest, PrimitiveType) {
+ UNITTEST::TestOneof2 message;
+ // Unset field returns default value
+ EXPECT_EQ(message.foo_int(), 0);
+
+ message.set_foo_int(123);
+ EXPECT_TRUE(message.has_foo_int());
+ EXPECT_EQ(message.foo_int(), 123);
+ message.clear_foo_int();
+ EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, EnumType) {
+ UNITTEST::TestOneof2 message;
+ // Unset field returns default value
+ EXPECT_EQ(message.foo_enum(), 1);
+
+ message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ EXPECT_TRUE(message.has_foo_enum());
+ EXPECT_EQ(message.foo_enum(), UNITTEST::TestOneof2::FOO);
+ message.clear_foo_enum();
+ EXPECT_FALSE(message.has_foo_enum());
+}
+
+TEST_F(OneofTest, SetString) {
+ // Check that setting a string field in various ways works
+ UNITTEST::TestOneof2 message;
+
+ // Unset field returns default value
+ EXPECT_EQ(message.foo_string(), "");
+
+ message.set_foo_string("foo");
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "foo");
+ message.clear_foo_string();
+ EXPECT_FALSE(message.has_foo_string());
+
+ message.set_foo_string(std::string("bar"));
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "bar");
+ message.clear_foo_string();
+ EXPECT_FALSE(message.has_foo_string());
+
+
+ message.set_foo_string("qux", 3);
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "qux");
+ message.clear_foo_string();
+ EXPECT_FALSE(message.has_foo_string());
+
+ message.mutable_foo_string()->assign("quux");
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "quux");
+ message.clear_foo_string();
+ EXPECT_FALSE(message.has_foo_string());
+
+ message.set_foo_string("corge");
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "corge");
+ message.clear_foo_string();
+ EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, ReleaseString) {
+ // Check that release_foo() starts out NULL, and gives us a value
+ // that we can delete after it's been set.
+ UNITTEST::TestOneof2 message;
+
+ EXPECT_EQ(NULL, message.release_foo_string());
+ EXPECT_FALSE(message.has_foo_string());
+
+ message.set_foo_string("blah");
+ EXPECT_TRUE(message.has_foo_string());
+ std::unique_ptr<std::string> str(message.release_foo_string());
+ EXPECT_FALSE(message.has_foo_string());
+ ASSERT_TRUE(str != NULL);
+ EXPECT_EQ("blah", *str);
+
+ EXPECT_EQ(NULL, message.release_foo_string());
+ EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, SetAllocatedString) {
+ // Check that set_allocated_foo() works for strings.
+ UNITTEST::TestOneof2 message;
+
+ EXPECT_FALSE(message.has_foo_string());
+ const std::string kHello("hello");
+ message.set_foo_string(kHello);
+ EXPECT_TRUE(message.has_foo_string());
+
+ message.set_allocated_foo_string(NULL);
+ EXPECT_FALSE(message.has_foo_string());
+ EXPECT_EQ("", message.foo_string());
+
+ message.set_allocated_foo_string(new std::string(kHello));
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(kHello, message.foo_string());
+}
+
+TEST_F(OneofTest, ArenaSetAllocatedString) {
+ // Check that set_allocated_foo() works for strings.
+ Arena arena;
+ UNITTEST::TestOneof2* message =
+ Arena::CreateMessage<UNITTEST::TestOneof2>(&arena);
+
+ EXPECT_FALSE(message->has_foo_string());
+ const std::string kHello("hello");
+ message->set_foo_string(kHello);
+ EXPECT_TRUE(message->has_foo_string());
+
+ message->set_allocated_foo_string(NULL);
+ EXPECT_FALSE(message->has_foo_string());
+ EXPECT_EQ("", message->foo_string());
+
+ message->set_allocated_foo_string(new std::string(kHello));
+ EXPECT_TRUE(message->has_foo_string());
+ EXPECT_EQ(kHello, message->foo_string());
+}
+
+
+TEST_F(OneofTest, SetMessage) {
+ // Check that setting a message field works
+ UNITTEST::TestOneof2 message;
+
+ // Unset field returns default instance
+ EXPECT_EQ(&message.foo_message(),
+ &UNITTEST::TestOneof2_NestedMessage::default_instance());
+ EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+ message.mutable_foo_message()->set_qux_int(234);
+ EXPECT_TRUE(message.has_foo_message());
+ EXPECT_EQ(message.foo_message().qux_int(), 234);
+ message.clear_foo_message();
+ EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, ReleaseMessage) {
+ // Check that release_foo() starts out NULL, and gives us a value
+ // that we can delete after it's been set.
+ UNITTEST::TestOneof2 message;
+
+ EXPECT_EQ(NULL, message.release_foo_message());
+ EXPECT_FALSE(message.has_foo_message());
+
+ message.mutable_foo_message()->set_qux_int(1);
+ EXPECT_TRUE(message.has_foo_message());
+ std::unique_ptr<UNITTEST::TestOneof2_NestedMessage> mes(
+ message.release_foo_message());
+ EXPECT_FALSE(message.has_foo_message());
+ ASSERT_TRUE(mes != NULL);
+ EXPECT_EQ(1, mes->qux_int());
+
+ EXPECT_EQ(NULL, message.release_foo_message());
+ EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, SetAllocatedMessage) {
+ // Check that set_allocated_foo() works for messages.
+ UNITTEST::TestOneof2 message;
+
+ EXPECT_FALSE(message.has_foo_message());
+
+ message.mutable_foo_message()->set_qux_int(1);
+ EXPECT_TRUE(message.has_foo_message());
+
+ message.set_allocated_foo_message(NULL);
+ EXPECT_FALSE(message.has_foo_message());
+ EXPECT_EQ(&message.foo_message(),
+ &UNITTEST::TestOneof2_NestedMessage::default_instance());
+
+ message.mutable_foo_message()->set_qux_int(1);
+ UNITTEST::TestOneof2_NestedMessage* mes = message.release_foo_message();
+ ASSERT_TRUE(mes != NULL);
+ EXPECT_FALSE(message.has_foo_message());
+
+ message.set_allocated_foo_message(mes);
+ EXPECT_TRUE(message.has_foo_message());
+ EXPECT_EQ(1, message.foo_message().qux_int());
+}
+
+
+TEST_F(OneofTest, Clear) {
+ UNITTEST::TestOneof2 message;
+
+ message.set_foo_int(1);
+ EXPECT_TRUE(message.has_foo_int());
+ message.clear_foo_int();
+ EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, Defaults) {
+ UNITTEST::TestOneof2 message;
+
+ EXPECT_FALSE(message.has_foo_int());
+ EXPECT_EQ(message.foo_int(), 0);
+
+ EXPECT_FALSE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "");
+
+
+ EXPECT_FALSE(message.has_foo_bytes());
+ EXPECT_EQ(message.foo_bytes(), "");
+
+ EXPECT_FALSE(message.has_foo_enum());
+ EXPECT_EQ(message.foo_enum(), 1);
+
+ EXPECT_FALSE(message.has_foo_message());
+ EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+ EXPECT_FALSE(message.has_foogroup());
+ EXPECT_EQ(message.foogroup().a(), 0);
+
+
+ EXPECT_FALSE(message.has_bar_int());
+ EXPECT_EQ(message.bar_int(), 5);
+
+ EXPECT_FALSE(message.has_bar_string());
+ EXPECT_EQ(message.bar_string(), "STRING");
+
+
+ EXPECT_FALSE(message.has_bar_bytes());
+ EXPECT_EQ(message.bar_bytes(), "BYTES");
+
+ EXPECT_FALSE(message.has_bar_enum());
+ EXPECT_EQ(message.bar_enum(), 2);
+}
+
+TEST_F(OneofTest, SwapWithEmpty) {
+ UNITTEST::TestOneof2 message1, message2;
+ message1.set_foo_string("FOO");
+ EXPECT_TRUE(message1.has_foo_string());
+ message1.Swap(&message2);
+ EXPECT_FALSE(message1.has_foo_string());
+ EXPECT_TRUE(message2.has_foo_string());
+ EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapWithSelf) {
+ UNITTEST::TestOneof2 message;
+ message.set_foo_string("FOO");
+ EXPECT_TRUE(message.has_foo_string());
+ message.Swap(&message);
+ EXPECT_TRUE(message.has_foo_string());
+ EXPECT_EQ(message.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapBothHasFields) {
+ UNITTEST::TestOneof2 message1, message2;
+
+ message1.set_foo_string("FOO");
+ EXPECT_TRUE(message1.has_foo_string());
+ message2.mutable_foo_message()->set_qux_int(1);
+ EXPECT_TRUE(message2.has_foo_message());
+
+ message1.Swap(&message2);
+ EXPECT_FALSE(message1.has_foo_string());
+ EXPECT_FALSE(message2.has_foo_message());
+ EXPECT_TRUE(message1.has_foo_message());
+ EXPECT_EQ(message1.foo_message().qux_int(), 1);
+ EXPECT_TRUE(message2.has_foo_string());
+ EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, CopyConstructor) {
+ UNITTEST::TestOneof2 message1;
+ message1.set_foo_bytes("FOO");
+
+ UNITTEST::TestOneof2 message2(message1);
+ EXPECT_TRUE(message2.has_foo_bytes());
+ EXPECT_EQ(message2.foo_bytes(), "FOO");
+}
+
+TEST_F(OneofTest, CopyFrom) {
+ UNITTEST::TestOneof2 message1, message2;
+ message1.set_foo_enum(UNITTEST::TestOneof2::BAR);
+ EXPECT_TRUE(message1.has_foo_enum());
+
+ message2.CopyFrom(message1);
+ EXPECT_TRUE(message2.has_foo_enum());
+ EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR);
+
+ // Copying from self should be a no-op.
+ message2.CopyFrom(message2);
+ EXPECT_TRUE(message2.has_foo_enum());
+ EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR);
+}
+
+TEST_F(OneofTest, CopyAssignmentOperator) {
+ UNITTEST::TestOneof2 message1;
+ message1.mutable_foo_message()->set_qux_int(123);
+ EXPECT_TRUE(message1.has_foo_message());
+
+ UNITTEST::TestOneof2 message2;
+ message2 = message1;
+ EXPECT_EQ(message2.foo_message().qux_int(), 123);
+
+ // Make sure that self-assignment does something sane.
+ message2 = *&message2; // Avoid -Wself-assign.
+ EXPECT_EQ(message2.foo_message().qux_int(), 123);
+}
+
+TEST_F(OneofTest, UpcastCopyFrom) {
+ // Test the CopyFrom method that takes in the generic const Message&
+ // parameter.
+ UNITTEST::TestOneof2 message1, message2;
+ message1.mutable_foogroup()->set_a(123);
+ EXPECT_TRUE(message1.has_foogroup());
+
+ const Message* source = implicit_cast<const Message*>(&message1);
+ message2.CopyFrom(*source);
+
+ EXPECT_TRUE(message2.has_foogroup());
+ EXPECT_EQ(message2.foogroup().a(), 123);
+}
+
+// Test the generated SerializeWithCachedSizesToArray(),
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToArray) {
+ // Primitive type
+ {
+ UNITTEST::TestOneof2 message1, message2;
+std::string data;
+message1.set_foo_int(123);
+int size = message1.ByteSizeLong();
+data.resize(size);
+uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+EXPECT_EQ(size, end - start);
+EXPECT_TRUE(message2.ParseFromString(data));
+EXPECT_EQ(message2.foo_int(), 123);
+ }
+
+ // String
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_string("foo");
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_string(), "foo");
+ }
+
+
+ // Bytes
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_bytes("qux");
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_bytes(), "qux");
+ }
+
+ // Enum
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+ }
+
+ // Message
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.mutable_foo_message()->set_qux_int(234);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_message().qux_int(), 234);
+ }
+
+ // Group
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.mutable_foogroup()->set_a(345);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+ uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+ uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foogroup().a(), 345);
+ }
+
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToStream) {
+ // Primitive type
+ {
+ UNITTEST::TestOneof2 message1, message2;
+std::string data;
+message1.set_foo_int(123);
+int size = message1.ByteSizeLong();
+data.resize(size);
+
+{
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+}
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_int(), 123);
+ }
+
+ // String
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_string("foo");
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_string(), "foo");
+ }
+
+
+ // Bytes
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_bytes("qux");
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_bytes(), "qux");
+ }
+
+ // Enum
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+ }
+
+ // Message
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.mutable_foo_message()->set_qux_int(234);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foo_message().qux_int(), 234);
+ }
+
+ // Group
+ {
+ UNITTEST::TestOneof2 message1, message2;
+ std::string data;
+ message1.mutable_foogroup()->set_a(345);
+ int size = message1.ByteSizeLong();
+ data.resize(size);
+
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+
+ EXPECT_TRUE(message2.ParseFromString(data));
+ EXPECT_EQ(message2.foogroup().a(), 345);
+ }
+
+}
+
+TEST_F(OneofTest, MergeFrom) {
+ UNITTEST::TestOneof2 message1, message2;
+
+ message1.set_foo_int(123);
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foo_int());
+ EXPECT_EQ(message2.foo_int(), 123);
+
+ message1.set_foo_string("foo");
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foo_string());
+ EXPECT_EQ(message2.foo_string(), "foo");
+
+
+ message1.set_foo_bytes("qux");
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foo_bytes());
+ EXPECT_EQ(message2.foo_bytes(), "qux");
+
+ message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foo_enum());
+ EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+
+ message1.mutable_foo_message()->set_qux_int(234);
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foo_message());
+ EXPECT_EQ(message2.foo_message().qux_int(), 234);
+
+ message1.mutable_foogroup()->set_a(345);
+ message2.MergeFrom(message1);
+ TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+ EXPECT_TRUE(message2.has_foogroup());
+ EXPECT_EQ(message2.foogroup().a(), 345);
+
+}
+
+TEST(HELPERS_TEST_NAME, TestSCC) {
+ UNITTEST::TestMutualRecursionA a;
+ MessageSCCAnalyzer scc_analyzer((Options()));
+ const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor());
+ std::vector<std::string> names;
+ names.reserve(scc->descriptors.size());
+ for (int i = 0; i < scc->descriptors.size(); i++) {
+ names.push_back(scc->descriptors[i]->full_name());
+ }
+ std::string package = a.GetDescriptor()->file()->package();
+ ASSERT_EQ(names.size(), 4);
+ std::sort(names.begin(), names.end());
+ EXPECT_EQ(names[0], package + ".TestMutualRecursionA");
+ EXPECT_EQ(names[1], package + ".TestMutualRecursionA.SubGroup");
+ EXPECT_EQ(names[2], package + ".TestMutualRecursionA.SubMessage");
+ EXPECT_EQ(names[3], package + ".TestMutualRecursionB");
+
+ MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+ EXPECT_EQ(result.is_recursive, true);
+ EXPECT_EQ(result.contains_required, false);
+ EXPECT_EQ(result.contains_cord, true); // TestAllTypes
+ EXPECT_EQ(result.contains_extension, false); // TestAllTypes
+}
+
+TEST(HELPERS_TEST_NAME, TestSCCAnalysis) {
+ {
+ UNITTEST::TestRecursiveMessage msg;
+ MessageSCCAnalyzer scc_analyzer((Options()));
+ const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+ MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+ EXPECT_EQ(result.is_recursive, true);
+ EXPECT_EQ(result.contains_required, false);
+ EXPECT_EQ(result.contains_cord, false);
+ EXPECT_EQ(result.contains_extension, false);
+ }
+ {
+ UNITTEST::TestAllExtensions msg;
+ MessageSCCAnalyzer scc_analyzer((Options()));
+ const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+ MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+ EXPECT_EQ(result.is_recursive, false);
+ EXPECT_EQ(result.contains_required, false);
+ EXPECT_EQ(result.contains_cord, false);
+ EXPECT_EQ(result.contains_extension, true);
+ }
+ {
+ UNITTEST::TestRequired msg;
+ MessageSCCAnalyzer scc_analyzer((Options()));
+ const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+ MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+ EXPECT_EQ(result.is_recursive, false);
+ EXPECT_EQ(result.contains_required, true);
+ EXPECT_EQ(result.contains_cord, false);
+ EXPECT_EQ(result.contains_extension, false);
+ }
+}
+
+} // namespace cpp_unittest
+} // namespace cpp
+} // namespace compiler
+
+namespace no_generic_services_test {
+ // Verify that no class called "TestService" was defined in
+ // unittest_no_generic_services.pb.h by defining a different type by the same
+ // name. If such a service was generated, this will not compile.
+ struct TestService {
+ int i;
+ };
+}
+
+namespace compiler {
+namespace cpp {
+namespace cpp_unittest {
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, NoGenericServices) {
+ // Verify that non-services in unittest_no_generic_services.proto were
+ // generated.
+ ::protobuf_unittest::no_generic_services_test::TestMessage message;
+ message.set_a(1);
+ message.SetExtension(
+ ::protobuf_unittest::no_generic_services_test::test_extension, 123);
+ ::protobuf_unittest::no_generic_services_test::TestEnum e =
+ ::protobuf_unittest::no_generic_services_test::FOO;
+ EXPECT_EQ(e, 1);
+
+ // Verify that a ServiceDescriptor is generated for the service even if the
+ // class itself is not.
+ const FileDescriptor* file =
+ ::google::protobuf::unittest::no_generic_services_test::TestMessage::descriptor()
+ ->file();
+
+ ASSERT_EQ(1, file->service_count());
+ EXPECT_EQ("TestService", file->service(0)->name());
+ ASSERT_EQ(1, file->service(0)->method_count());
+ EXPECT_EQ("Foo", file->service(0)->method(0)->name());
+}
+
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+// This test must run last. It verifies that descriptors were or were not
+// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined.
+// When this is defined, we skip all tests which are expected to trigger
+// descriptor initialization. This verifies that everything else still works
+// if descriptors are not initialized.
+TEST(DESCRIPTOR_INIT_TEST_NAME, Initialized) {
+#ifdef PROTOBUF_TEST_NO_DESCRIPTORS
+ bool should_have_descriptors = false;
+#else
+ bool should_have_descriptors = true;
+#endif
+
+ EXPECT_EQ(should_have_descriptors,
+ DescriptorPool::generated_pool()->InternalIsFileLoaded(
+ TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH)));
+}
+
+} // namespace cpp_unittest
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/cpp/metadata_test.cc b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/metadata_test.cc
new file mode 100644
index 00000000..bbd043d1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/cpp/metadata_test.cc
@@ -0,0 +1,161 @@
+// 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>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/cpp/cpp_helpers.h>
+#include <compiler/cpp/cpp_generator.h>
+#include <compiler/annotation_test_util.h>
+#include <compiler/command_line_interface.h>
+#include <descriptor.pb.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace atu = annotation_test_util;
+
+namespace {
+
+class CppMetadataTest : public ::testing::Test {
+ public:
+ // 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 std::string& filename, FileDescriptorProto* file,
+ std::string* pb_h, GeneratedCodeInfo* pb_h_info,
+ std::string* proto_h, GeneratedCodeInfo* proto_h_info,
+ std::string* pb_cc) {
+ CommandLineInterface cli;
+ CppGenerator cpp_generator;
+ cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+ std::string cpp_out =
+ "--cpp_out=annotate_headers=true,"
+ "annotation_pragma_name=pragma_name,"
+ "annotation_guard_name=guard_name:" +
+ TestTempDir();
+
+ const bool result = atu::RunProtoCompiler(filename, cpp_out, &cli, file);
+
+ if (!result) {
+ return result;
+ }
+
+ std::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 (!atu::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 (!atu::DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+const char kSmallTestFile[] =
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "enum Enum { VALUE = 0; }\n"
+ "message Message { }\n";
+
+TEST_F(CppMetadataTest, CapturesEnumNames) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ std::string pb_h;
+ atu::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 =
+ atu::FindAnnotationOnPath(info, "test.proto", enum_path);
+ EXPECT_TRUE(NULL != enum_annotation);
+ EXPECT_TRUE(atu::AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
+}
+
+TEST_F(CppMetadataTest, AddsPragma) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ std::string pb_h;
+ atu::AddFile("test.proto", kSmallTestFile);
+ EXPECT_TRUE(
+ CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+ EXPECT_TRUE(pb_h.find("#ifdef guard_name") != std::string::npos);
+ EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
+ std::string::npos);
+}
+
+TEST_F(CppMetadataTest, CapturesMessageNames) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ std::string pb_h;
+ atu::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 =
+ atu::FindAnnotationOnPath(info, "test.proto", message_path);
+ EXPECT_TRUE(NULL != message_annotation);
+ EXPECT_TRUE(
+ atu::AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
+}
+
+} // namespace
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
new file mode 100644
index 00000000..371b12ca
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -0,0 +1,194 @@
+// 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 test insures that
+// csharp/src/Google.Protobuf/Reflection/Descriptor.cs match exactly
+// what would be generated by the protocol compiler. The file is not
+// generated automatically at build time.
+//
+// If this test fails, run the script
+// "generate_descriptor_proto.sh" and add the changed files under
+// csharp/src/ to your changelist.
+
+#include <map>
+
+#include <compiler/csharp/csharp_generator.h>
+#include <compiler/importer.h>
+#include <descriptor.h>
+#include <io/zero_copy_stream_impl.h>
+#include <stubs/map_util.h>
+#include <stubs/stl_util.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+namespace {
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+ MockErrorCollector() {}
+ ~MockErrorCollector() {}
+
+ std::string text_;
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, int line, int column,
+ const std::string& message) {
+ strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+ filename, line, column, message);
+ }
+};
+
+class MockGeneratorContext : public GeneratorContext {
+ public:
+ void ExpectFileMatches(const std::string& virtual_filename,
+ const std::string& physical_filename) {
+ auto it = files_.find(virtual_filename);
+ ASSERT_TRUE(it != files_.end())
+ << "Generator failed to generate file: " << virtual_filename;
+ std::string expected_contents = *it->second;
+
+ std::string actual_contents;
+ GOOGLE_CHECK_OK(
+ File::GetContentsAsText(TestSourceDir() + "/" + physical_filename,
+ &actual_contents, true))
+ << "Unable to get " << physical_filename;
+ EXPECT_TRUE(actual_contents == expected_contents)
+ << physical_filename << " needs to be regenerated. Please run "
+ "generate_descriptor_proto.sh. Then add this file "
+ "to your CL.";
+ }
+
+ // implements GeneratorContext --------------------------------------
+
+ virtual io::ZeroCopyOutputStream* Open(const std::string& filename) {
+ auto& map_slot = files_[filename];
+ map_slot.reset(new std::string);
+ return new io::StringOutputStream(map_slot.get());
+ }
+
+ private:
+ std::map<std::string, std::unique_ptr<std::string>> files_;
+};
+
+class GenerateAndTest {
+ public:
+ GenerateAndTest() {}
+ void Run(const FileDescriptor* proto_file, std::string file1, std::string file2) {
+ ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
+ ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
+ &context_, &error_));
+ context_.ExpectFileMatches(file1, file2);
+ }
+ void SetParameter(string parameter) {
+ parameter_ = parameter;
+ }
+
+ private:
+ Generator generator_;
+ MockGeneratorContext context_;
+ std::string error_;
+ std::string parameter_;
+};
+
+TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
+ // Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
+ // only distribution).
+ std::string descriptor_file_name =
+ "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
+ if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
+ return;
+ }
+
+ MockErrorCollector error_collector;
+ DiskSourceTree source_tree;
+ Importer importer(&source_tree, &error_collector);
+ GenerateAndTest generate_test;
+
+ generate_test.SetParameter("base_namespace=Google.Protobuf");
+ source_tree.MapPath("", TestSourceDir());
+ generate_test.Run(importer.Import("google/protobuf/descriptor.proto"),
+ "Reflection/Descriptor.cs",
+ "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs");
+ generate_test.Run(importer.Import("google/protobuf/any.proto"),
+ "WellKnownTypes/Any.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Any.cs");
+ generate_test.Run(importer.Import("google/protobuf/api.proto"),
+ "WellKnownTypes/Api.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Api.cs");
+ generate_test.Run(importer.Import("google/protobuf/duration.proto"),
+ "WellKnownTypes/Duration.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs");
+ generate_test.Run(importer.Import("google/protobuf/empty.proto"),
+ "WellKnownTypes/Empty.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs");
+ generate_test.Run(importer.Import("google/protobuf/field_mask.proto"),
+ "WellKnownTypes/FieldMask.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs");
+ generate_test.Run(importer.Import("google/protobuf/source_context.proto"),
+ "WellKnownTypes/SourceContext.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs");
+ generate_test.Run(importer.Import("google/protobuf/struct.proto"),
+ "WellKnownTypes/Struct.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs");
+ generate_test.Run(importer.Import("google/protobuf/timestamp.proto"),
+ "WellKnownTypes/Timestamp.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs");
+ generate_test.Run(importer.Import("google/protobuf/type.proto"),
+ "WellKnownTypes/Type.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Type.cs");
+ generate_test.Run(importer.Import("google/protobuf/wrappers.proto"),
+ "WellKnownTypes/Wrappers.cs",
+ "../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
+
+ generate_test.SetParameter("");
+ source_tree.MapPath("", TestSourceDir() + "/../conformance");
+ generate_test.Run(importer.Import("conformance.proto"),
+ "Conformance.cs",
+ "../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
+
+ EXPECT_EQ("", error_collector.text_);
+}
+
+} // namespace
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.cc
new file mode 100644
index 00000000..12dabe04
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <descriptor.h>
+#include <io/printer.h>
+#include <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) {
+ std::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, "&", "&amp;", true);
+ comments = StringReplace(comments, "<", "&lt;", true);
+ std::vector<std::string> lines;
+ lines = Split(comments, "\n", false);
+ // 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<std::string>::iterator it = lines.begin();
+ it != lines.end(); ++it) {
+ std::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
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.h
new file mode 100644
index 00000000..ca78e251
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_doc_comment.h
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
+
+#include <io/printer.h>
+#include <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__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.cc
new file mode 100644
index 00000000..fd96c571
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.cc
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_enum.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_options.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
+ SourceGeneratorBase(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<std::string> used_names;
+ std::set<int> used_number;
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ std::string original_name = descriptor_->value(i)->name();
+ std::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 += "_";
+ }
+ int number = descriptor_->value(i)->number();
+ if (!used_number.insert(number).second) {
+ printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
+ "original_name", original_name,
+ "name", name,
+ "number", StrCat(number));
+ } else {
+ printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
+ "original_name", original_name,
+ "name", name,
+ "number", StrCat(number));
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.h
new file mode 100644
index 00000000..d589ae50
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum.h
@@ -0,0 +1,66 @@
+// 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 <compiler/code_generator.h>
+#include <compiler/csharp/csharp_source_generator_base.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumGenerator : public SourceGeneratorBase {
+ public:
+ EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
+ ~EnumGenerator();
+
+ EnumGenerator(const EnumGenerator&) = delete;
+ EnumGenerator& operator=(const EnumGenerator&) = delete;
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.cc
new file mode 100644
index 00000000..76a47674
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {
+}
+
+void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_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, $default_value$)");
+}
+
+void EnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::Extension<$extended_type$, $type_name$>($number$, ");
+ GenerateCodecCode(printer);
+ printer->Print(");\n");
+}
+
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
+}
+
+EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
+}
+
+void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
+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
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.h
new file mode 100644
index 00000000..791ff21a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_enum_field.h
@@ -0,0 +1,83 @@
+// 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 <compiler/code_generator.h>
+#include <compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class EnumFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+ EnumFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~EnumFieldGenerator();
+
+ EnumFieldGenerator(const EnumFieldGenerator&) = delete;
+ EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
+
+ virtual void GenerateCodecCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+};
+
+class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
+ public:
+ EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~EnumOneofFieldGenerator();
+
+ EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete;
+ EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete;
+
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.cc
new file mode 100644
index 00000000..52934b04
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.cc
@@ -0,0 +1,459 @@
+// 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 <cmath>
+#include <limits>
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+#include <wire_format.h>
+
+#include <compiler/csharp/csharp_field_base.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_names.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+void FieldGeneratorBase::SetCommonFieldVariables(
+ std::map<std::string, std::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());
+ int part_tag_size = tag_size;
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ part_tag_size /= 2;
+ }
+ uint tag = internal::WireFormat::MakeTag(descriptor_);
+ uint8 tag_array[5];
+ io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+ std::string tag_bytes = StrCat(tag_array[0]);
+ for (int i = 1; i < part_tag_size; i++) {
+ tag_bytes += ", " + StrCat(tag_array[i]);
+ }
+
+ (*variables)["tag"] = StrCat(tag);
+ (*variables)["tag_size"] = StrCat(tag_size);
+ (*variables)["tag_bytes"] = tag_bytes;
+
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
+ tag = internal::WireFormatLite::MakeTag(
+ descriptor_->number(),
+ internal::WireFormatLite::WIRETYPE_END_GROUP);
+ io::CodedOutputStream::WriteTagToArray(tag, tag_array);
+ tag_bytes = StrCat(tag_array[0]);
+ for (int i = 1; i < part_tag_size; i++) {
+ tag_bytes += ", " + StrCat(tag_array[i]);
+ }
+
+ variables_["end_tag"] = StrCat(tag);
+ variables_["end_tag_bytes"] = tag_bytes;
+ }
+
+ (*variables)["access_level"] = "public";
+
+ (*variables)["property_name"] = property_name();
+ (*variables)["type_name"] = type_name();
+ (*variables)["extended_type"] = GetClassName(descriptor_->containing_type());
+ (*variables)["name"] = name();
+ (*variables)["descriptor_name"] = descriptor_->name();
+ (*variables)["default_value"] = default_value();
+ (*variables)["capitalized_type_name"] = capitalized_type_name();
+ (*variables)["number"] = number();
+ if (has_default_value() && !SupportsPresenceApi(descriptor_)) {
+ (*variables)["name_def_message"] =
+ (*variables)["name"] + "_ = " + (*variables)["default_value"];
+ } else {
+ (*variables)["name_def_message"] = (*variables)["name"] + "_";
+ }
+ if (SupportsPresenceApi(descriptor_)) {
+ (*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
+ (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
+ (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
+ (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
+ if (presenceIndex_ != -1) {
+ std::string hasBitsNumber = StrCat(presenceIndex_ / 32);
+ std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
+ (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
+ (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
+ (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
+ }
+ } else {
+ (*variables)["has_property_check"] =
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ (*variables)["other_has_property_check"] = "other." +
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ }
+}
+
+void FieldGeneratorBase::SetCommonOneofFieldVariables(
+ std::map<std::string, std::string>* variables) {
+ (*variables)["oneof_name"] = oneof_name();
+ if (SupportsPresenceApi(descriptor_)) {
+ (*variables)["has_property_check"] = "Has" + property_name();
+ } else {
+ (*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 presenceIndex, const Options* options)
+ : SourceGeneratorBase(options),
+ descriptor_(descriptor),
+ presenceIndex_(presenceIndex) {
+ 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::GenerateExtensionCode(io::Printer* printer) {
+ // No-op: only message fields, enum fields, primitives,
+ // and repeated fields need this default is to not generate any code
+}
+
+void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ // for some field types the value of "use_parse_context" doesn't matter,
+ // so we fallback to the default implementation.
+ GenerateParsingCode(printer);
+}
+
+void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ // for some field types the value of "use_write_context" doesn't matter,
+ // so we fallback to the default implementation.
+ GenerateSerializationCode(printer);
+}
+
+void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
+ if (descriptor_->options().deprecated()) {
+ printer->Print("[global::System.ObsoleteAttribute]\n");
+ } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
+ descriptor_->message_type()->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);
+ std::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 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(const FieldDescriptor* descriptor) {
+ if (descriptor->default_value_string().empty())
+ return "\"\"";
+ else
+ return "global::System.Text.Encoding.UTF8.GetString(global::System."
+ "Convert.FromBase64String(\"" +
+ StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")";
+}
+
+std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
+ if (descriptor->default_value_string().empty())
+ return "pb::ByteString.Empty";
+ else
+ return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
+}
+
+std::string FieldGeneratorBase::default_value() {
+ return default_value(descriptor_);
+}
+
+std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ return GetClassName(descriptor->default_value_enum()->type()) + "." +
+ GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
+ 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 == std::numeric_limits<double>::infinity()) {
+ return "double.PositiveInfinity";
+ } else if (value == -std::numeric_limits<double>::infinity()) {
+ return "double.NegativeInfinity";
+ } else if (std::isnan(value)) {
+ return "double.NaN";
+ }
+ return StrCat(value) + "D";
+ }
+ case FieldDescriptor::TYPE_FLOAT: {
+ float value = descriptor->default_value_float();
+ if (value == std::numeric_limits<float>::infinity()) {
+ return "float.PositiveInfinity";
+ } else if (value == -std::numeric_limits<float>::infinity()) {
+ return "float.NegativeInfinity";
+ } else if (std::isnan(value)) {
+ return "float.NaN";
+ }
+ return StrCat(value) + "F";
+ }
+ case FieldDescriptor::TYPE_INT64:
+ return StrCat(descriptor->default_value_int64()) + "L";
+ case FieldDescriptor::TYPE_UINT64:
+ return StrCat(descriptor->default_value_uint64()) + "UL";
+ case FieldDescriptor::TYPE_INT32:
+ return StrCat(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_FIXED64:
+ return StrCat(descriptor->default_value_uint64()) + "UL";
+ case FieldDescriptor::TYPE_FIXED32:
+ return StrCat(descriptor->default_value_uint32());
+ case FieldDescriptor::TYPE_BOOL:
+ if (descriptor->default_value_bool()) {
+ return "true";
+ } else {
+ return "false";
+ }
+ case FieldDescriptor::TYPE_STRING:
+ return GetStringDefaultValueInternal(descriptor);
+ case FieldDescriptor::TYPE_BYTES:
+ return GetBytesDefaultValueInternal(descriptor);
+ case FieldDescriptor::TYPE_UINT32:
+ return StrCat(descriptor->default_value_uint32());
+ case FieldDescriptor::TYPE_SFIXED32:
+ return StrCat(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_SFIXED64:
+ return StrCat(descriptor->default_value_int64()) + "L";
+ case FieldDescriptor::TYPE_SINT32:
+ return StrCat(descriptor->default_value_int32());
+ case FieldDescriptor::TYPE_SINT64:
+ return StrCat(descriptor->default_value_int64()) + "L";
+ default:
+ GOOGLE_LOG(FATAL)<< "Unknown field type.";
+ return "";
+ }
+}
+
+std::string FieldGeneratorBase::number() {
+ return StrCat(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
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.h
new file mode 100644
index 00000000..f0221b6c
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_field_base.h
@@ -0,0 +1,111 @@
+// 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 <stubs/strutil.h>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_source_generator_base.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase : public SourceGeneratorBase {
+ public:
+ FieldGeneratorBase(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options* options);
+ ~FieldGeneratorBase();
+
+ FieldGeneratorBase(const FieldGeneratorBase&) = delete;
+ FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) = 0;
+ virtual void GenerateFreezingCode(io::Printer* printer);
+ virtual void GenerateCodecCode(io::Printer* printer);
+ virtual void GenerateExtensionCode(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 GenerateParsingCode(io::Printer* printer, bool use_parse_context);
+ virtual void GenerateSerializationCode(io::Printer* printer) = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
+ 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 presenceIndex_;
+ std::map<std::string, std::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(
+ std::map<std::string, std::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();
+ std::string default_value();
+ std::string default_value(const FieldDescriptor* descriptor);
+ std::string number();
+ std::string capitalized_type_name();
+
+ private:
+ void SetCommonFieldVariables(std::map<std::string, std::string>* variables);
+ std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
+ std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.cc
new file mode 100644
index 00000000..ded055fb
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.cc
@@ -0,0 +1,112 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+#include <compiler/csharp/csharp_generator.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_names.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_reflection_class.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+Generator::Generator() {}
+Generator::~Generator() {}
+
+uint64_t Generator::GetSupportedFeatures() const {
+ return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
+void GenerateFile(const FileDescriptor* file, io::Printer* printer,
+ const Options* options) {
+ ReflectionClassGenerator reflectionClassGenerator(file, options);
+ reflectionClassGenerator.Generate(printer);
+}
+
+bool Generator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+
+ 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 if (options[i].first == "serializable") {
+ cli_options.serializable = true;
+ } else {
+ *error = "Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ std::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;
+ }
+ std::unique_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
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.h
new file mode 100644
index 00000000..6f030cb2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates C# code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// CodeGenerator implementation which generates a C# source file and
+// header. If you create your own protocol compiler binary and you want
+// it to support C# output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+ Generator();
+ ~Generator();
+ bool Generate(
+ const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+ uint64_t GetSupportedFeatures() const override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator_unittest.cc
new file mode 100644
index 00000000..c03f8855
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <memory>
+
+#include <compiler/command_line_interface.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <io/zero_copy_stream.h>
+#include <io/printer.h>
+
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+namespace {
+
+TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
+ EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+ EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+ EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
+ EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
+ EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
+ EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
+ EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
+ EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
+ EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+ EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+ EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
+ EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
+ // Identifiers can't start with digits
+ EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
+ EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
+}
+
+} // namespace
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.cc
new file mode 100644
index 00000000..b703187d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.cc
@@ -0,0 +1,592 @@
+// 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 <algorithm>
+#include <limits>
+#include <vector>
+#include <sstream>
+
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_names.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+#include <compiler/csharp/csharp_field_base.h>
+#include <compiler/csharp/csharp_enum_field.h>
+#include <compiler/csharp/csharp_map_field.h>
+#include <compiler/csharp/csharp_message_field.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_primitive_field.h>
+#include <compiler/csharp/csharp_repeated_enum_field.h>
+#include <compiler/csharp/csharp_repeated_message_field.h>
+#include <compiler/csharp/csharp_repeated_primitive_field.h>
+#include <compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+CSharpType GetCSharpType(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_INT64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_UINT32:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_UINT64:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_SINT32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_SINT64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_FIXED32:
+ return CSHARPTYPE_UINT32;
+ case FieldDescriptor::TYPE_FIXED64:
+ return CSHARPTYPE_UINT64;
+ case FieldDescriptor::TYPE_SFIXED32:
+ return CSHARPTYPE_INT32;
+ case FieldDescriptor::TYPE_SFIXED64:
+ return CSHARPTYPE_INT64;
+ case FieldDescriptor::TYPE_FLOAT:
+ return CSHARPTYPE_FLOAT;
+ case FieldDescriptor::TYPE_DOUBLE:
+ return CSHARPTYPE_DOUBLE;
+ case FieldDescriptor::TYPE_BOOL:
+ return CSHARPTYPE_BOOL;
+ case FieldDescriptor::TYPE_ENUM:
+ return CSHARPTYPE_ENUM;
+ case FieldDescriptor::TYPE_STRING:
+ return CSHARPTYPE_STRING;
+ case FieldDescriptor::TYPE_BYTES:
+ return CSHARPTYPE_BYTESTRING;
+ case FieldDescriptor::TYPE_GROUP:
+ return CSHARPTYPE_MESSAGE;
+ case FieldDescriptor::TYPE_MESSAGE:
+ return CSHARPTYPE_MESSAGE;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL)<< "Can't get here.";
+ return (CSharpType) -1;
+}
+
+std::string StripDotProto(const std::string& proto_file) {
+ int lastindex = proto_file.find_last_of(".");
+ return proto_file.substr(0, lastindex);
+}
+
+std::string GetFileNamespace(const FileDescriptor* descriptor) {
+ if (descriptor->options().has_csharp_namespace()) {
+ return descriptor->options().csharp_namespace();
+ }
+ return UnderscoresToCamelCase(descriptor->package(), true, true);
+}
+
+// Returns the Pascal-cased last part of the proto file. For example,
+// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
+std::string GetFileNameBase(const FileDescriptor* descriptor) {
+ std::string proto_file = descriptor->name();
+ int lastslash = proto_file.find_last_of("/");
+ std::string base = proto_file.substr(lastslash + 1);
+ return UnderscoresToPascalCase(StripDotProto(base));
+}
+
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
+ // TODO: Detect collisions with existing messages,
+ // and append an underscore if necessary.
+ return GetFileNameBase(descriptor) + "Reflection";
+}
+
+std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) {
+ // TODO: Detect collisions with existing messages,
+ // and append an underscore if necessary.
+ return GetFileNameBase(descriptor) + "Extensions";
+}
+
+// TODO(jtattermusch): can we reuse a utility function?
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter,
+ bool preserve_period) {
+ std::string result;
+ // Note: I distrust ctype.h due to locales.
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_next_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ if (i == 0 && !cap_next_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += input[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_next_letter = true;
+ } else {
+ cap_next_letter = true;
+ if (input[i] == '.' && preserve_period) {
+ result += '.';
+ }
+ }
+ }
+ // Add a trailing "_" if the name should be altered.
+ if (input.size() > 0 && input[input.size() - 1] == '#') {
+ result += '_';
+ }
+ return result;
+}
+
+std::string UnderscoresToPascalCase(const std::string& input) {
+ return UnderscoresToCamelCase(input, true);
+}
+
+// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
+// into a PascalCase string. Precise rules implemented:
+
+// Previous input character Current character Case
+// Any Non-alphanumeric Skipped
+// None - first char of input Alphanumeric Upper
+// Non-letter (e.g. _ or 1) Alphanumeric Upper
+// Numeric Alphanumeric Upper
+// Lower letter Alphanumeric Same as current
+// Upper letter Alphanumeric Lower
+std::string ShoutyToPascalCase(const std::string& input) {
+ std::string result;
+ // Simple way of implementing "always start with upper"
+ char previous = '_';
+ for (int i = 0; i < input.size(); i++) {
+ char current = input[i];
+ if (!ascii_isalnum(current)) {
+ previous = current;
+ continue;
+ }
+ if (!ascii_isalnum(previous)) {
+ result += ascii_toupper(current);
+ } else if (ascii_isdigit(previous)) {
+ result += ascii_toupper(current);
+ } else if (ascii_islower(previous)) {
+ result += current;
+ } else {
+ result += ascii_tolower(current);
+ }
+ previous = current;
+ }
+ return result;
+}
+
+// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
+// (foo, foo_bar) => bar - underscore after prefix is skipped
+// (FOO, foo_bar) => bar - casing is ignored
+// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
+// (foobar, foo_barbaz) => baz - underscore in value is ignored
+// (foo, bar) => bar - prefix isn't matched; return original value
+std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
+ // First normalize to a lower-case no-underscores prefix to match against
+ std::string prefix_to_match = "";
+ for (size_t i = 0; i < prefix.size(); i++) {
+ if (prefix[i] != '_') {
+ prefix_to_match += ascii_tolower(prefix[i]);
+ }
+ }
+
+ // This keeps track of how much of value we've consumed
+ size_t prefix_index, value_index;
+ for (prefix_index = 0, value_index = 0;
+ prefix_index < prefix_to_match.size() && value_index < value.size();
+ value_index++) {
+ // Skip over underscores in the value
+ if (value[value_index] == '_') {
+ continue;
+ }
+ if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
+ // Failed to match the prefix - bail out early.
+ return value;
+ }
+ }
+
+ // If we didn't finish looking through the prefix, we can't strip it.
+ if (prefix_index < prefix_to_match.size()) {
+ return value;
+ }
+
+ // Step over any underscores after the prefix
+ while (value_index < value.size() && value[value_index] == '_') {
+ value_index++;
+ }
+
+ // If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
+ if (value_index == value.size()) {
+ return value;
+ }
+
+ return value.substr(value_index);
+}
+
+// Format the enum value name in a pleasant way for C#:
+// - Strip the enum name as a prefix if possible
+// - Convert to PascalCase.
+// For example, an enum called Color with a value of COLOR_BLUE should
+// result in an enum value in C# called just Blue
+std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
+ std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
+ std::string result = ShoutyToPascalCase(stripped);
+ // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
+ // string is a valid identifier.
+ if (ascii_isdigit(result[0])) {
+ result = "_" + result;
+ }
+ return result;
+}
+
+uint GetGroupEndTag(const Descriptor* descriptor) {
+ const Descriptor* containing_type = descriptor->containing_type();
+ if (containing_type != NULL) {
+ const FieldDescriptor* field;
+ for (int i = 0; i < containing_type->field_count(); i++) {
+ field = containing_type->field(i);
+ if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
+ field->message_type() == descriptor) {
+ return internal::WireFormatLite::MakeTag(
+ field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
+ }
+ }
+ for (int i = 0; i < containing_type->extension_count(); i++) {
+ field = containing_type->extension(i);
+ if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
+ field->message_type() == descriptor) {
+ return internal::WireFormatLite::MakeTag(
+ field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
+ }
+ }
+ } else {
+ const FileDescriptor* containing_file = descriptor->file();
+ if (containing_file != NULL) {
+ const FieldDescriptor* field;
+ for (int i = 0; i < containing_file->extension_count(); i++) {
+ field = containing_file->extension(i);
+ if (field->type() == FieldDescriptor::Type::TYPE_GROUP &&
+ field->message_type() == descriptor) {
+ return internal::WireFormatLite::MakeTag(
+ field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
+ std::string result = GetFileNamespace(file);
+ if (!result.empty()) {
+ result += '.';
+ }
+ std::string classname;
+ if (file->package().empty()) {
+ classname = name;
+ } else {
+ // Strip the proto package from full_name since we've replaced it with
+ // the C# namespace.
+ classname = name.substr(file->package().size() + 1);
+ }
+ result += StringReplace(classname, ".", ".Types.", true);
+ return "global::" + result;
+}
+
+std::string GetReflectionClassName(const FileDescriptor* descriptor) {
+ std::string result = GetFileNamespace(descriptor);
+ if (!result.empty()) {
+ result += '.';
+ }
+ result += GetReflectionClassUnqualifiedName(descriptor);
+ return "global::" + result;
+}
+
+std::string GetFullExtensionName(const FieldDescriptor* descriptor) {
+ if (descriptor->extension_scope()) {
+ return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor);
+ }
+ else {
+ return GetExtensionClassUnqualifiedName(descriptor->file()) + "." + GetPropertyName(descriptor);
+ }
+}
+
+std::string GetClassName(const Descriptor* descriptor) {
+ return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+std::string GetClassName(const EnumDescriptor* descriptor) {
+ return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+// Groups are hacky: The name of the field is just the lower-cased name
+// of the group type. In C#, though, we would like to retain the original
+// capitalization of the type name.
+std::string GetFieldName(const FieldDescriptor* descriptor) {
+ if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+ return descriptor->message_type()->name();
+ } else {
+ return descriptor->name();
+ }
+}
+
+std::string GetFieldConstantName(const FieldDescriptor* field) {
+ return GetPropertyName(field) + "FieldNumber";
+}
+
+std::string GetPropertyName(const FieldDescriptor* descriptor) {
+ // TODO(jtattermusch): consider introducing csharp_property_name field option
+ std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
+ // Avoid either our own type name or reserved names. Note that not all names
+ // are reserved - a field called to_string, write_to etc would still cause a problem.
+ // There are various ways of ending up with naming collisions, but we try to avoid obvious
+ // ones.
+ if (property_name == descriptor->containing_type()->name()
+ || property_name == "Types"
+ || property_name == "Descriptor") {
+ property_name += "_";
+ }
+ return property_name;
+}
+
+std::string GetOutputFile(const FileDescriptor* descriptor,
+ const std::string file_extension,
+ const bool generate_directories,
+ const std::string base_namespace,
+ std::string* error) {
+ std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
+ if (!generate_directories) {
+ return relative_filename;
+ }
+ std::string ns = GetFileNamespace(descriptor);
+ std::string namespace_suffix = ns;
+ if (!base_namespace.empty()) {
+ // Check that the base_namespace is either equal to or a leading part of
+ // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
+ // be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
+ // to both.
+ std::string extended_ns = ns + ".";
+ if (extended_ns.find(base_namespace + ".") != 0) {
+ *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace;
+ return ""; // This will be ignored, because we've set an error.
+ }
+ namespace_suffix = ns.substr(base_namespace.length());
+ if (namespace_suffix.find(".") == 0) {
+ namespace_suffix = namespace_suffix.substr(1);
+ }
+ }
+
+ std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+ if (!namespace_dir.empty()) {
+ namespace_dir += "/";
+ }
+ return namespace_dir + relative_filename;
+}
+
+// TODO: c&p from Java protoc plugin
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int GetFixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32 : return -1;
+ case FieldDescriptor::TYPE_INT64 : return -1;
+ case FieldDescriptor::TYPE_UINT32 : return -1;
+ case FieldDescriptor::TYPE_UINT64 : return -1;
+ case FieldDescriptor::TYPE_SINT32 : return -1;
+ case FieldDescriptor::TYPE_SINT64 : return -1;
+ case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL : return internal::WireFormatLite::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM : return -1;
+
+ case FieldDescriptor::TYPE_STRING : return -1;
+ case FieldDescriptor::TYPE_BYTES : return -1;
+ case FieldDescriptor::TYPE_GROUP : return -1;
+ case FieldDescriptor::TYPE_MESSAGE : return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::string StringToBase64(const std::string& input) {
+ std::string result;
+ size_t remaining = input.size();
+ const unsigned char *src = (const unsigned char*) input.c_str();
+ while (remaining > 2) {
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+ result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
+ result += base64_chars[src[2] & 0x3f];
+ remaining -= 3;
+ src += 3;
+ }
+ switch (remaining) {
+ case 2:
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
+ result += base64_chars[(src[1] & 0xf) << 2];
+ result += '=';
+ src += 2;
+ break;
+ case 1:
+ result += base64_chars[src[0] >> 2];
+ result += base64_chars[((src[0] & 0x3) << 4)];
+ result += '=';
+ result += '=';
+ src += 1;
+ break;
+ }
+ return result;
+}
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
+ std::string fdp_bytes;
+ FileDescriptorProto fdp;
+ descriptor->CopyTo(&fdp);
+ fdp.SerializeToString(&fdp_bytes);
+ return StringToBase64(fdp_bytes);
+}
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options* options) {
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ if (descriptor->is_repeated()) {
+ if (descriptor->is_map()) {
+ return new MapFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
+ }
+ } else {
+ if (IsWrapperType(descriptor)) {
+ if (descriptor->real_containing_oneof()) {
+ return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ return new WrapperFieldGenerator(descriptor, presenceIndex, options);
+ }
+ } else {
+ if (descriptor->real_containing_oneof()) {
+ return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ return new MessageFieldGenerator(descriptor, presenceIndex, options);
+ }
+ }
+ }
+ case FieldDescriptor::TYPE_ENUM:
+ if (descriptor->is_repeated()) {
+ return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ if (descriptor->real_containing_oneof()) {
+ return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ return new EnumFieldGenerator(descriptor, presenceIndex, options);
+ }
+ }
+ default:
+ if (descriptor->is_repeated()) {
+ return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ if (descriptor->real_containing_oneof()) {
+ return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
+ } else {
+ return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
+ }
+ }
+ }
+}
+
+bool IsNullable(const FieldDescriptor* descriptor) {
+ if (descriptor->is_repeated()) {
+ return true;
+ }
+
+ 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;
+ }
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.h
new file mode 100644
index 00000000..74d97152
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_helpers.h
@@ -0,0 +1,195 @@
+// 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_CSHARP_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
+
+#include <string>
+#include <port.h>
+#include <stubs/common.h>
+#include <descriptor.pb.h>
+#include <descriptor.h>
+#include <compiler/code_generator.h>
+#include <io/printer.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+class FieldGeneratorBase;
+
+// TODO: start using this enum.
+enum CSharpType {
+ CSHARPTYPE_INT32 = 1,
+ CSHARPTYPE_INT64 = 2,
+ CSHARPTYPE_UINT32 = 3,
+ CSHARPTYPE_UINT64 = 4,
+ CSHARPTYPE_FLOAT = 5,
+ CSHARPTYPE_DOUBLE = 6,
+ CSHARPTYPE_BOOL = 7,
+ CSHARPTYPE_STRING = 8,
+ CSHARPTYPE_BYTESTRING = 9,
+ CSHARPTYPE_MESSAGE = 10,
+ CSHARPTYPE_ENUM = 11,
+ MAX_CSHARPTYPE = 11
+};
+
+// Converts field type to corresponding C# type.
+CSharpType GetCSharpType(FieldDescriptor::Type type);
+
+std::string StripDotProto(const std::string& proto_file);
+
+// Gets unqualified name of the reflection class
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
+// Gets unqualified name of the extension class
+std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
+
+std::string GetClassName(const EnumDescriptor* descriptor);
+
+std::string GetFieldName(const FieldDescriptor* descriptor);
+
+std::string GetFieldConstantName(const FieldDescriptor* field);
+
+std::string GetPropertyName(const FieldDescriptor* descriptor);
+
+int GetFixedSize(FieldDescriptor::Type type);
+
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter,
+ bool preserve_period);
+
+inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
+ return UnderscoresToCamelCase(input, cap_next_letter, false);
+}
+
+std::string UnderscoresToPascalCase(const std::string& input);
+
+// Note that we wouldn't normally want to export this (we're not expecting
+// it to be used outside libprotoc itself) but this exposes it for testing.
+std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name,
+ const std::string& enum_value_name);
+
+// TODO(jtattermusch): perhaps we could move this to strutil
+std::string StringToBase64(const std::string& input);
+
+std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
+
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options* options);
+
+std::string GetFullExtensionName(const FieldDescriptor* descriptor);
+
+bool IsNullable(const FieldDescriptor* descriptor);
+
+// Determines whether the given message is a map entry message,
+// i.e. one implicitly created by protoc due to a map<key, value> field.
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group
+uint GetGroupEndTag(const Descriptor* descriptor);
+
+// Determines whether we're generating code for the proto representation of
+// descriptors etc, for use in the runtime. This is the only type which is
+// allowed to use proto2 syntax, and it generates internal classes.
+inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
+ return descriptor->name() == "google/protobuf/descriptor.proto";
+}
+
+// Determines whether the given message is an options message within descriptor.proto.
+inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
+ if (!IsDescriptorProto(descriptor->file())) {
+ return false;
+ }
+ const std::string name = descriptor->full_name();
+ return name == "google.protobuf.FileOptions" ||
+ name == "google.protobuf.MessageOptions" ||
+ name == "google.protobuf.FieldOptions" ||
+ name == "google.protobuf.OneofOptions" ||
+ name == "google.protobuf.EnumOptions" ||
+ name == "google.protobuf.EnumValueOptions" ||
+ name == "google.protobuf.ServiceOptions" ||
+ name == "google.protobuf.MethodOptions";
+}
+
+inline bool IsWrapperType(const FieldDescriptor* descriptor) {
+ return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
+}
+
+inline bool IsProto2(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
+inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
+ // Unlike most languages, we don't generate Has/Clear members for message
+ // types, because they can always be set to null in C#. They're not really
+ // needed for oneof fields in proto2 either, as everything can be done via
+ // oneof case, but we follow the convention from other languages. Proto3
+ // oneof fields never have Has/Clear members - but will also never have
+ // the explicit optional keyword either.
+ //
+ // None of the built-in helpers (descriptor->has_presence() etc) describe
+ // quite the behavior we want, so the rules are explicit below.
+
+ if (descriptor->is_repeated() ||
+ descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
+ return false;
+ }
+ // has_optional_keyword() has more complex rules for proto2, but that
+ // doesn't matter given the first part of this condition.
+ return IsProto2(descriptor->file()) || descriptor->has_optional_keyword();
+}
+
+inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
+ return SupportsPresenceApi(descriptor) &&
+ !IsNullable(descriptor) &&
+ !descriptor->is_extension() &&
+ !descriptor->real_containing_oneof();
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.cc
new file mode 100644
index 00000000..7b4015da
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.cc
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_map_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options* options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+}
+
+MapFieldGenerator::~MapFieldGenerator() {
+}
+
+void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
+ const FieldDescriptor* key_descriptor =
+ descriptor_->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ variables_["key_type_name"] = type_name(key_descriptor);
+ variables_["value_type_name"] = type_name(value_descriptor);
+ std::unique_ptr<FieldGeneratorBase> key_generator(
+ CreateFieldGenerator(key_descriptor, 1, this->options()));
+ std::unique_ptr<FieldGeneratorBase> value_generator(
+ CreateFieldGenerator(value_descriptor, 2, this->options()));
+
+ printer->Print(
+ variables_,
+ "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
+ " = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
+ key_generator->GenerateCodecCode(printer);
+ printer->Print(", ");
+ value_generator->GenerateCodecCode(printer);
+ printer->Print(
+ variables_,
+ ", $tag$);\n"
+ "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"
+ : "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
+ : "$name$_.WriteTo(output, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $property_name$.GetHashCode();\n");
+}
+void MapFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (!$property_name$.Equals(other.$property_name$)) return false;\n");
+}
+
+void MapFieldGenerator::WriteToString(io::Printer* printer) {
+ // TODO: If we ever actually use ToString, we'll need to impleme this...
+}
+
+void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.h
new file mode 100644
index 00000000..de16588c
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_map_field.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MapFieldGenerator : public FieldGeneratorBase {
+ public:
+ MapFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options* options);
+ ~MapFieldGenerator();
+
+ MapFieldGenerator(const MapFieldGenerator&) = delete;
+ MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateFreezingCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
new file mode 100644
index 00000000..963b9c87
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.cc
@@ -0,0 +1,779 @@
+// 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 <algorithm>
+#include <map>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_enum.h>
+#include <compiler/csharp/csharp_field_base.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_message.h>
+#include <compiler/csharp/csharp_names.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
+ return d1->number() < d2->number();
+}
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+ const Options* options)
+ : SourceGeneratorBase(options),
+ descriptor_(descriptor),
+ has_bit_field_count_(0),
+ end_tag_(GetGroupEndTag(descriptor)),
+ has_extension_ranges_(descriptor->extension_range_count() > 0) {
+ // fields by number
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ fields_by_number_.push_back(descriptor_->field(i));
+ }
+ std::sort(fields_by_number_.begin(), fields_by_number_.end(),
+ CompareFieldNumbers);
+
+ int presence_bit_count = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (RequiresPresenceBit(field)) {
+ presence_bit_count++;
+ if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) {
+ has_bit_field_count_++;
+ }
+ }
+ }
+}
+
+MessageGenerator::~MessageGenerator() {
+}
+
+std::string MessageGenerator::class_name() {
+ return descriptor_->name();
+}
+
+std::string MessageGenerator::full_class_name() {
+ return GetClassName(descriptor_);
+}
+
+const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
+ return fields_by_number_;
+}
+
+void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
+ if (descriptor_->options().deprecated()) {
+ printer->Print("[global::System.ObsoleteAttribute]\n");
+ }
+}
+
+void MessageGenerator::AddSerializableAttribute(io::Printer* printer) {
+ if (this->options()->serializable) {
+ printer->Print("[global::System.SerializableAttribute]\n");
+ }
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+ vars["access_level"] = class_access_level();
+
+ WriteMessageDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ AddSerializableAttribute(printer);
+
+ printer->Print(
+ vars,
+ "$access_level$ sealed partial class $class_name$ : ");
+
+ if (has_extension_ranges_) {
+ printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
+ }
+ else {
+ printer->Print(vars, "pb::IMessage<$class_name$>\n");
+ }
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Print(" , pb::IBufferMessage\n");
+ printer->Print("#endif\n");
+ printer->Print("{\n");
+ printer->Indent();
+
+ // All static fields and properties
+ printer->Print(
+ vars,
+ "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
+
+ printer->Print(
+ "private pb::UnknownFieldSet _unknownFields;\n");
+
+ if (has_extension_ranges_) {
+ if (IsDescriptorProto(descriptor_->file())) {
+ printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility
+ } else {
+ printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
+ }
+
+ // a read-only property for fast
+ // retrieval of the set in IsInitialized
+ printer->Print(vars,
+ "private pb::ExtensionSet<$class_name$> _Extensions { get { "
+ "return _extensions; } }\n");
+ }
+
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ // don't use arrays since all arrays are heap allocated, saving allocations
+ // use ints instead of bytes since bytes lack bitwise operators, saving casts
+ printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
+ }
+
+ WriteGeneratedCodeAttributes(printer);
+
+ printer->Print(
+ vars,
+ "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
+
+ // Access the message descriptor via the relevant file descriptor or containing message descriptor.
+ if (!descriptor_->containing_type()) {
+ vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
+ + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
+ } else {
+ vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
+ + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
+ }
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public static pbr::MessageDescriptor Descriptor {\n"
+ " get { return $descriptor_accessor$; }\n"
+ "}\n"
+ "\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
+ " get { return Descriptor; }\n"
+ "}\n"
+ "\n");
+
+ // Parameterless constructor and partial OnConstruction method.
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $class_name$() {\n"
+ " OnConstruction();\n"
+ "}\n\n"
+ "partial void OnConstruction();\n\n");
+
+ GenerateCloningCode(printer);
+ GenerateFreezingCode(printer);
+
+ // Fields/properties
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+
+ // Rats: we lose the debug comment here :(
+ printer->Print(
+ "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
+ "public const int $field_constant_name$ = $index$;\n",
+ "field_name", fieldDescriptor->name(),
+ "field_constant_name", GetFieldConstantName(fieldDescriptor),
+ "index", StrCat(fieldDescriptor->number()));
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fieldDescriptor));
+ generator->GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ // oneof properties (for real oneofs, which come before synthetic ones)
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ vars["original_name"] = oneof->name();
+ printer->Print(
+ vars,
+ "private object $name$_;\n"
+ "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
+ "public enum $property_name$OneofCase {\n");
+ printer->Indent();
+ printer->Print("None = 0,\n");
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ printer->Print("$field_property_name$ = $index$,\n",
+ "field_property_name", GetPropertyName(field),
+ "index", StrCat(field->number()));
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ // TODO: Should we put the oneof .proto comments here?
+ // It's unclear exactly where they should go.
+ printer->Print(
+ vars,
+ "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $property_name$OneofCase $property_name$Case {\n"
+ " get { return $name$Case_; }\n"
+ "}\n\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public void Clear$property_name$() {\n"
+ " $name$Case_ = $property_name$OneofCase.None;\n"
+ " $name$_ = null;\n"
+ "}\n\n");
+ }
+
+ // Standard methods
+ GenerateFrameworkMethods(printer);
+ GenerateMessageSerializationMethods(printer);
+ GenerateMergingMethods(printer);
+
+ if (has_extension_ranges_) {
+ printer->Print(
+ vars,
+ "public TValue GetExtension<TValue>(pb::Extension<$class_name$, "
+ "TValue> extension) {\n"
+ " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
+ "}\n"
+ "public pbc::RepeatedField<TValue> "
+ "GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
+ "extension) {\n"
+ " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
+ "}\n"
+ "public pbc::RepeatedField<TValue> "
+ "GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, "
+ "TValue> extension) {\n"
+ " return pb::ExtensionSet.GetOrInitialize(ref _extensions, "
+ "extension);\n"
+ "}\n"
+ "public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> "
+ "extension, TValue value) {\n"
+ " pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
+ "}\n"
+ "public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> "
+ "extension) {\n"
+ " return pb::ExtensionSet.Has(ref _extensions, extension);\n"
+ "}\n"
+ "public void ClearExtension<TValue>(pb::Extension<$class_name$, "
+ "TValue> extension) {\n"
+ " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
+ "}\n"
+ "public void "
+ "ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
+ "extension) {\n"
+ " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
+ "}\n\n");
+ }
+
+ // Nested messages and enums
+ if (HasNestedGeneratedTypes()) {
+ printer->Print(
+ vars,
+ "#region Nested types\n"
+ "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public static partial class Types {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
+ enumGenerator.Generate(printer);
+ }
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate nested types for maps...
+ if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
+ MessageGenerator messageGenerator(
+ descriptor_->nested_type(i), this->options());
+ messageGenerator.Generate(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n"
+ "#endregion\n"
+ "\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print(
+ vars,
+ "#region Extensions\n"
+ "/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public static partial class Extensions {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->extension(i)));
+ generator->GenerateExtensionCode(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "#endregion\n"
+ "\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+}
+
+// Helper to work out whether we need to generate a class to hold nested types/enums.
+// Only tricky because we don't want to generate map entry types.
+bool MessageGenerator::HasNestedGeneratedTypes()
+{
+ if (descriptor_->enum_type_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ WriteGeneratedCodeAttributes(printer);
+ vars["class_name"] = class_name();
+ printer->Print(
+ vars,
+ "public $class_name$($class_name$ other) : this() {\n");
+ printer->Indent();
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
+ }
+ // Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->real_containing_oneof()) {
+ continue;
+ }
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateCloningCode(printer);
+ }
+ // Clone just the right field for each real oneof
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ vars["field_property_name"] = GetPropertyName(field);
+ printer->Print(
+ vars,
+ "case $property_name$OneofCase.$field_property_name$:\n");
+ printer->Indent();
+ generator->GenerateCloningCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ // Clone unknown fields
+ printer->Print(
+ "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
+ if (has_extension_ranges_) {
+ printer->Print(
+ "_extensions = pb::ExtensionSet.Clone(other._extensions);\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public $class_name$ Clone() {\n"
+ " return new $class_name$(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+
+ // Equality
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public override bool Equals(object other) {\n"
+ " return Equals(other as $class_name$);\n"
+ "}\n\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public bool Equals($class_name$ other) {\n"
+ " if (ReferenceEquals(other, null)) {\n"
+ " return false;\n"
+ " }\n"
+ " if (ReferenceEquals(other, this)) {\n"
+ " return true;\n"
+ " }\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteEquals(printer);
+ }
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
+ "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (!Equals(_extensions, other._extensions)) {\n"
+ " return false;\n"
+ "}\n");
+ }
+ printer->Outdent();
+ printer->Print(
+ " return Equals(_unknownFields, other._unknownFields);\n"
+ "}\n\n");
+
+ // GetHashCode
+ // Start with a non-zero value to easily distinguish between null and "empty" messages.
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public override int GetHashCode() {\n"
+ " int hash = 1;\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->WriteHash(printer);
+ }
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ printer->Print("hash ^= (int) $name$Case_;\n",
+ "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (_extensions != null) {\n"
+ " hash ^= _extensions.GetHashCode();\n"
+ "}\n");
+ }
+ printer->Print(
+ "if (_unknownFields != null) {\n"
+ " hash ^= _unknownFields.GetHashCode();\n"
+ "}\n"
+ "return hash;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public override string ToString() {\n"
+ " return pb::JsonFormatter.ToDiagnosticString(this);\n"
+ "}\n\n");
+}
+
+void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public void WriteTo(pb::CodedOutputStream output) {\n");
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Indent();
+ printer->Print("output.WriteRawMessage(this);\n");
+ printer->Outdent();
+ printer->Print("#else\n");
+ printer->Indent();
+ GenerateWriteToBody(printer, false);
+ printer->Outdent();
+ printer->Print("#endif\n");
+ printer->Print("}\n\n");
+
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n");
+ printer->Indent();
+ GenerateWriteToBody(printer, true);
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("#endif\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ "public int CalculateSize() {\n");
+ printer->Indent();
+ printer->Print("int size = 0;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateSerializedSizeCode(printer);
+ }
+
+ if (has_extension_ranges_) {
+ printer->Print(
+ "if (_extensions != null) {\n"
+ " size += _extensions.CalculateSize();\n"
+ "}\n");
+ }
+
+ printer->Print(
+ "if (_unknownFields != null) {\n"
+ " size += _unknownFields.CalculateSize();\n"
+ "}\n");
+
+ printer->Print("return size;\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) {
+ // Serialize all the fields
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(fields_by_number()[i]));
+ generator->GenerateSerializationCode(printer, use_write_context);
+ }
+
+ if (has_extension_ranges_) {
+ // Serialize extensions
+ printer->Print(
+ use_write_context
+ ? "if (_extensions != null) {\n"
+ " _extensions.WriteTo(ref output);\n"
+ "}\n"
+ : "if (_extensions != null) {\n"
+ " _extensions.WriteTo(output);\n"
+ "}\n");
+ }
+
+ // Serialize unknown fields
+ printer->Print(
+ use_write_context
+ ? "if (_unknownFields != null) {\n"
+ " _unknownFields.WriteTo(ref output);\n"
+ "}\n"
+ : "if (_unknownFields != null) {\n"
+ " _unknownFields.WriteTo(output);\n"
+ "}\n");
+
+ // TODO(jonskeet): Memoize size of frozen messages?
+}
+
+void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ std::map<std::string, std::string> vars;
+ vars["class_name"] = class_name();
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print(
+ vars,
+ "public void MergeFrom($class_name$ other) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (other == null) {\n"
+ " return;\n"
+ "}\n");
+ // Merge non-oneof fields, treating optional proto3 fields as normal fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->real_containing_oneof()) {
+ continue;
+ }
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateMergingCode(printer);
+ }
+ // Merge oneof fields (for non-synthetic oneofs)
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
+ vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
+ printer->Print(vars, "switch (other.$property_name$Case) {\n");
+ printer->Indent();
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ vars["field_property_name"] = GetPropertyName(field);
+ printer->Print(
+ vars,
+ "case $property_name$OneofCase.$field_property_name$:\n");
+ printer->Indent();
+ std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+ generator->GenerateMergingCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ // Merge extensions
+ if (has_extension_ranges_) {
+ printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n");
+ }
+
+ // Merge unknown fields.
+ printer->Print(
+ "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ printer->Indent();
+ printer->Print("input.ReadRawMessage(this);\n");
+ printer->Outdent();
+ printer->Print("#else\n");
+ printer->Indent();
+ GenerateMainParseLoop(printer, false);
+ printer->Outdent();
+ printer->Print("#endif\n");
+ printer->Print("}\n\n");
+
+ printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+ WriteGeneratedCodeAttributes(printer);
+ printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n");
+ printer->Indent();
+ GenerateMainParseLoop(printer, true);
+ printer->Outdent();
+ printer->Print("}\n"); // method
+ printer->Print("#endif\n\n");
+
+}
+
+void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) {
+ std::map<std::string, std::string> vars;
+ vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
+
+ printer->Print(
+ "uint tag;\n"
+ "while ((tag = input.ReadTag()) != 0) {\n"
+ " switch(tag) {\n");
+ printer->Indent();
+ printer->Indent();
+ if (end_tag_ != 0) {
+ printer->Print(
+ "case $end_tag$:\n"
+ " return;\n",
+ "end_tag", StrCat(end_tag_));
+ }
+ if (has_extension_ranges_) {
+ printer->Print(vars,
+ "default:\n"
+ " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n"
+ " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
+ " }\n"
+ " break;\n");
+ } else {
+ printer->Print(vars,
+ "default:\n"
+ " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n"
+ " break;\n");
+ }
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ const FieldDescriptor* field = fields_by_number()[i];
+ internal::WireFormatLite::WireType wt =
+ internal::WireFormat::WireTypeForFieldType(field->type());
+ uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
+ // Handle both packed and unpacked repeated fields with the same Read*Array call;
+ // the two generated cases are the packed and unpacked tags.
+ // TODO(jonskeet): Check that is_packable is equivalent to
+ // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
+ // It looks like it is...
+ if (field->is_packable()) {
+ printer->Print(
+ "case $packed_tag$:\n",
+ "packed_tag",
+ StrCat(
+ internal::WireFormatLite::MakeTag(
+ field->number(),
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
+ }
+
+ printer->Print("case $tag$: {\n", "tag", StrCat(tag));
+ printer->Indent();
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(field));
+ generator->GenerateParsingCode(printer, use_parse_context);
+ printer->Print("break;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n"); // switch
+ printer->Outdent();
+ printer->Print("}\n"); // while
+}
+
+// it's a waste of space to track presence for all values, so we only track them if they're not nullable
+int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
+ if (!RequiresPresenceBit(descriptor)) {
+ return -1;
+ }
+
+ int index = 0;
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ const FieldDescriptor* field = fields_by_number()[i];
+ if (field == descriptor) {
+ return index;
+ }
+ if (RequiresPresenceBit(field)) {
+ index++;
+ }
+ }
+ GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
+ return -1;
+}
+
+FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
+ const FieldDescriptor* descriptor) {
+ return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.h
new file mode 100644
index 00000000..cdb31f80
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message.h
@@ -0,0 +1,94 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
+
+#include <string>
+#include <vector>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_source_generator_base.h>
+#include <compiler/csharp/csharp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class FieldGeneratorBase;
+
+class MessageGenerator : public SourceGeneratorBase {
+ public:
+ MessageGenerator(const Descriptor* descriptor, const Options* options);
+ ~MessageGenerator();
+
+ MessageGenerator(const MessageGenerator&) = delete;
+ MessageGenerator& operator=(const MessageGenerator&) = delete;
+
+ void GenerateCloningCode(io::Printer* printer);
+ void GenerateFreezingCode(io::Printer* printer);
+ void GenerateFrameworkMethods(io::Printer* printer);
+ void Generate(io::Printer* printer);
+
+ private:
+ const Descriptor* descriptor_;
+ std::vector<const FieldDescriptor*> fields_by_number_;
+ int has_bit_field_count_;
+ uint end_tag_;
+ bool has_extension_ranges_;
+
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateWriteToBody(io::Printer* printer, bool use_write_context);
+ void GenerateMergingMethods(io::Printer* printer);
+ void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context);
+
+ int GetPresenceIndex(const FieldDescriptor* descriptor);
+ FieldGeneratorBase* CreateFieldGeneratorInternal(
+ const FieldDescriptor* descriptor);
+
+ bool HasNestedGeneratedTypes();
+
+ void AddDeprecatedFlag(io::Printer* printer);
+ void AddSerializableAttribute(io::Printer* printer);
+
+ std::string class_name();
+ std::string full_class_name();
+
+ // field descriptors sorted by number
+ const std::vector<const FieldDescriptor*>& fields_by_number();
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.cc
new file mode 100644
index 00000000..1252202e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.cc
@@ -0,0 +1,293 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_message_field.h>
+#include <compiler/csharp/csharp_options.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+ if (!SupportsPresenceApi(descriptor_)) {
+ variables_["has_property_check"] = name() + "_ != null";
+ variables_["has_not_property_check"] = name() + "_ == null";
+ }
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {
+
+}
+
+void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private $type_name$ $name$_;\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ "}\n");
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $name$_ != null; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " $name$_ = null;\n"
+ "}\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (other.$has_property_check$) {\n"
+ " if ($has_not_property_check$) {\n"
+ " $property_name$ = new $type_name$();\n"
+ " }\n"
+ " $property_name$.MergeFrom(other.$property_name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_not_property_check$) {\n"
+ " $property_name$ = new $type_name$();\n"
+ "}\n");
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+ printer->Print(variables_, "input.ReadMessage($property_name$);\n");
+ } else {
+ printer->Print(variables_, "input.ReadGroup($property_name$);\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteMessage($property_name$);\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.WriteGroup($property_name$);\n"
+ " output.WriteRawTag($end_tag_bytes$);\n"
+ "}\n");
+ }
+}
+
+void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
+ "}\n");
+ }
+}
+
+void MessageFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+}
+void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
+}
+void MessageFieldGenerator::WriteToString(io::Printer* printer) {
+ variables_["field_name"] = GetFieldName(descriptor_);
+ printer->Print(
+ variables_,
+ "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
+}
+void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::Extension<$extended_type$, $type_name$>($number$, ");
+ GenerateCodecCode(printer);
+ printer->Print(");\n");
+}
+void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
+}
+
+void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+ } else {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
+ }
+}
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options)
+ : MessageFieldGenerator(descriptor, presenceIndex, options) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
+
+}
+
+void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
+ " set {\n"
+ " $oneof_name$_ = value;\n"
+ " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "if ($property_name$ == null) {\n"
+ " $property_name$ = new $type_name$();\n"
+ "}\n"
+ "$property_name$.MergeFrom(other.$property_name$);\n");
+}
+
+void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ // TODO(jonskeet): We may be able to do better than this
+ printer->Print(
+ variables_,
+ "$type_name$ subBuilder = new $type_name$();\n"
+ "if ($has_property_check$) {\n"
+ " subBuilder.MergeFrom($property_name$);\n"
+ "}\n");
+ if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
+ printer->Print("input.ReadMessage(subBuilder);\n");
+ } else {
+ printer->Print("input.ReadGroup(subBuilder);\n");
+ }
+ printer->Print(variables_, "$property_name$ = subBuilder;\n");
+}
+
+void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$.Clone();\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.h
new file mode 100644
index 00000000..4cea5197
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_message_field.h
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MessageFieldGenerator : public FieldGeneratorBase {
+ public:
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~MessageFieldGenerator();
+
+ MessageFieldGenerator(const MessageFieldGenerator&) = delete;
+ MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
+
+ virtual void GenerateCodecCode(io::Printer* printer) override;
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateFreezingCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+};
+
+class MessageOneofFieldGenerator : public MessageFieldGenerator {
+ public:
+ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~MessageOneofFieldGenerator();
+
+ MessageOneofFieldGenerator(const MessageOneofFieldGenerator&) = delete;
+ MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) =
+ delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_names.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_names.h
new file mode 100644
index 00000000..247951ef
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_names.h
@@ -0,0 +1,109 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Provides a mechanism for mapping a descriptor to the
+// fully-qualified name of the corresponding C# class.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
+
+#include <string>
+#include <port.h>
+#include <stubs/common.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace csharp {
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The namespace to use for given file descriptor.
+std::string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified C# class name.
+std::string PROTOC_EXPORT GetClassName(const Descriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified name of the C# class that provides
+// access to the file descriptor. Proto compiler generates
+// such class for each .proto file processed.
+std::string PROTOC_EXPORT
+GetReflectionClassName(const FileDescriptor* descriptor);
+
+// Generates output file name for given file descriptor. If generate_directories
+// is true, the output file will be put under directory corresponding to file's
+// namespace. base_namespace can be used to strip some of the top level
+// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar",
+// the resulting file will be put under directory "Foo" (and not "Bar/Foo").
+//
+// Requires:
+// descriptor != NULL
+// error != NULL
+//
+// Returns:
+// The file name to use as output file for given file descriptor. In case
+// of failure, this function will return empty string and error parameter
+// will contain the error message.
+std::string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor,
+ const std::string file_extension,
+ const bool generate_directories,
+ const std::string base_namespace,
+ std::string* error);
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_options.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_options.h
new file mode 100644
index 00000000..42ff6d86
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_options.h
@@ -0,0 +1,81 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Generator options (used by csharp_generator.cc):
+struct Options {
+ Options() :
+ file_extension(".cs"),
+ base_namespace(""),
+ base_namespace_specified(false),
+ internal_access(false),
+ serializable(false) {
+ }
+ // Extension of the generated file. Defaults to ".cs"
+ std::string file_extension;
+ // Base namespace to use to create directory hierarchy. Defaults to "".
+ // This option allows the simple creation of a conventional C# file layout,
+ // where directories are created relative to a project-specific base
+ // namespace. For example, in a project with a base namespace of PetShop, a
+ // proto of user.proto with a C# namespace of PetShop.Model.Shared would
+ // generate Model/Shared/User.cs underneath the specified --csharp_out
+ // directory.
+ //
+ // If no base namespace is specified, all files are generated in the
+ // --csharp_out directory, with no subdirectories created automatically.
+ std::string base_namespace;
+ // Whether the base namespace has been explicitly specified by the user.
+ // This is required as the base namespace can be explicitly set to the empty
+ // string, meaning "create a full directory hierarchy, starting from the first
+ // segment of the namespace."
+ bool base_namespace_specified;
+ // Whether the generated classes should have accessibility level of "internal".
+ // Defaults to false that generates "public" classes.
+ bool internal_access;
+ // Whether the generated classes should have a global::System.Serializable attribute added
+ // Defaults to false
+ bool serializable;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.cc
new file mode 100644
index 00000000..6f695aa8
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -0,0 +1,349 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+ // TODO(jonskeet): Make this cleaner...
+ is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
+ && descriptor->type() != FieldDescriptor::TYPE_BYTES;
+ if (!is_value_type && !SupportsPresenceApi(descriptor_)) {
+ variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
+ variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
+ }
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
+}
+
+void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+
+ // Note: in multiple places, this code assumes that all fields
+ // that support presence are either nullable, or use a presence field bit.
+ // Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below.
+ // Extensions are not generated here either.
+
+
+ // Proto2 allows different default values to be specified. These are retained
+ // via static fields. They don't particularly need to be, but we don't need
+ // to change that. In Proto3 the default value we don't generate these
+ // fields, just using the literal instead.
+ if (IsProto2(descriptor_->file())) {
+ // Note: "private readonly static" isn't as idiomatic as
+ // "private static readonly", but changing this now would create a lot of
+ // churn in generated code with near-to-zero benefit.
+ printer->Print(
+ variables_,
+ "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
+ variables_["default_value_access"] =
+ variables_["property_name"] + "DefaultValue";
+ } else {
+ variables_["default_value_access"] = variables_["default_value"];
+ }
+
+ // Declare the field itself.
+ printer->Print(
+ variables_,
+ "private $type_name$ $name_def_message$;\n");
+
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+
+ // Most of the work is done in the property:
+ // Declare the property itself (the same for all options)
+ printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n");
+
+ // Specify the "getter", which may need to check for a presence field.
+ if (SupportsPresenceApi(descriptor_)) {
+ if (IsNullable(descriptor_)) {
+ printer->Print(
+ variables_,
+ " get { return $name$_ ?? $default_value_access$; }\n");
+ } else {
+ printer->Print(
+ variables_,
+ // Note: it's possible that this could be rewritten as a
+ // conditional ?: expression, but there's no significant benefit
+ // to changing it.
+ " get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n");
+ }
+ } else {
+ printer->Print(
+ variables_,
+ " get { return $name$_; }\n");
+ }
+
+ // Specify the "setter", which may need to set a field bit as well as the
+ // value.
+ printer->Print(" set {\n");
+ if (presenceIndex_ != -1) {
+ printer->Print(
+ variables_,
+ " $set_has_field$;\n");
+ }
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ " $name$_ = value;\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+ }
+ printer->Print(
+ " }\n"
+ "}\n");
+
+ // The "HasFoo" property, where required.
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return ");
+ if (IsNullable(descriptor_)) {
+ printer->Print(
+ variables_,
+ "$name$_ != null; }\n}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "$has_field_check$; }\n}\n");
+ }
+ }
+
+ // The "ClearFoo" method, where required.
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(variables_,
+ "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n");
+ if (IsNullable(descriptor_)) {
+ printer->Print(variables_, " $name$_ = null;\n");
+ } else {
+ printer->Print(variables_, " $clear_has_field$;\n");
+ }
+ printer->Print("}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($other_has_property_check$) {\n"
+ " $property_name$ = other.$property_name$;\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ // Note: invoke the property setter rather than writing straight to the field,
+ // so that we can normalize "null to empty" for strings and bytes.
+ printer->Print(
+ variables_,
+ "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " output.WriteRawTag($tag_bytes$);\n"
+ " output.Write$capitalized_type_name$($property_name$);\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n");
+ printer->Indent();
+ int fixedSize = GetFixedSize(descriptor_->type());
+ if (fixedSize == -1) {
+ printer->Print(
+ variables_,
+ "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
+ } else {
+ printer->Print(
+ "size += $tag_size$ + $fixed_size$;\n",
+ "fixed_size", StrCat(fixedSize),
+ "tag_size", variables_["tag_size"]);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+ const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+ if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+ text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n";
+ } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+ text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n";
+ }
+ printer->Print(variables_, text);
+}
+void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+ const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+ if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+ text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+ } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+ text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+ }
+ printer->Print(variables_, text);
+}
+void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_;\n");
+}
+
+void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.For$capitalized_type_name$($tag$, $default_value$)");
+}
+
+void PrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::Extension<$extended_type$, $type_name$>($number$, ");
+ GenerateCodecCode(printer);
+ printer->Print(");\n");
+}
+
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
+ " set {\n");
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ " $oneof_name$_ = value;\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+ }
+ printer->Print(
+ variables_,
+ " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$property_name$ = input.Read$capitalized_type_name$();\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$;\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.h
new file mode 100644
index 00000000..2386331e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -0,0 +1,97 @@
+// 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_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class PrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~PrimitiveFieldGenerator();
+
+ PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
+ PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
+
+ virtual void GenerateCodecCode(io::Printer* printer) override;
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+
+ protected:
+ bool is_value_type;
+};
+
+class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
+ public:
+ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~PrimitiveOneofFieldGenerator();
+
+ PrimitiveOneofFieldGenerator(const PrimitiveOneofFieldGenerator&) = delete;
+ PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) =
+ delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.cc
new file mode 100644
index 00000000..5975f313
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -0,0 +1,330 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+
+#include <compiler/csharp/csharp_enum.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_field_base.h>
+#include <compiler/csharp/csharp_message.h>
+#include <compiler/csharp/csharp_names.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_reflection_class.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
+ const Options* options)
+ : SourceGeneratorBase(options),
+ file_(file) {
+ namespace_ = GetFileNamespace(file);
+ reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
+ extensionClassname_ = GetExtensionClassUnqualifiedName(file);
+}
+
+ReflectionClassGenerator::~ReflectionClassGenerator() {
+}
+
+void ReflectionClassGenerator::Generate(io::Printer* printer) {
+ WriteIntroduction(printer);
+
+ WriteDescriptor(printer);
+ // Close the class declaration.
+ printer->Outdent();
+ printer->Print("}\n");
+
+ if (file_->extension_count() > 0) {
+ printer->Print(
+ "/// <summary>Holder for extension identifiers generated from the top "
+ "level of $file_name$</summary>\n"
+ "$access_level$ static partial class $class_name$ {\n",
+ "access_level", class_access_level(), "class_name", extensionClassname_,
+ "file_name", file_->name());
+ printer->Indent();
+ for (int i = 0; i < file_->extension_count(); i++) {
+ std::unique_ptr<FieldGeneratorBase> generator(
+ CreateFieldGenerator(file_->extension(i), -1, this->options()));
+ generator->GenerateExtensionCode(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+ }
+
+ // write children: Enums
+ if (file_->enum_type_count() > 0) {
+ printer->Print("#region Enums\n");
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator enumGenerator(file_->enum_type(i), this->options());
+ enumGenerator.Generate(printer);
+ }
+ printer->Print("#endregion\n");
+ printer->Print("\n");
+ }
+
+ // write children: Messages
+ if (file_->message_type_count() > 0) {
+ printer->Print("#region Messages\n");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i), this->options());
+ messageGenerator.Generate(printer);
+ }
+ printer->Print("#endregion\n");
+ printer->Print("\n");
+ }
+
+ // TODO(jtattermusch): add insertion point for services.
+
+ if (!namespace_.empty()) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print("\n");
+ printer->Print("#endregion Designer generated code\n");
+}
+
+void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
+ printer->Print(
+ "// <auto-generated>\n"
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $file_name$\n"
+ "// </auto-generated>\n"
+ "#pragma warning disable 1591, 0612, 3021\n"
+ "#region Designer generated code\n"
+ "\n"
+ "using pb = global::Google.Protobuf;\n"
+ "using pbc = global::Google.Protobuf.Collections;\n"
+ "using pbr = global::Google.Protobuf.Reflection;\n"
+ "using scg = global::System.Collections.Generic;\n",
+ "file_name", file_->name());
+
+ if (!namespace_.empty()) {
+ printer->Print("namespace $namespace$ {\n", "namespace", namespace_);
+ printer->Indent();
+ printer->Print("\n");
+ }
+
+ printer->Print(
+ "/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
+ "$access_level$ static partial class $reflection_class_name$ {\n"
+ "\n",
+ "file_name", file_->name(),
+ "access_level", class_access_level(),
+ "reflection_class_name", reflectionClassname_);
+ printer->Indent();
+}
+
+void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) {
+ printer->Print(
+ "#region Descriptor\n"
+ "/// <summary>File descriptor for $file_name$</summary>\n"
+ "public static pbr::FileDescriptor Descriptor {\n"
+ " get { return descriptor; }\n"
+ "}\n"
+ "private static pbr::FileDescriptor descriptor;\n"
+ "\n"
+ "static $reflection_class_name$() {\n",
+ "file_name", file_->name(),
+ "reflection_class_name", reflectionClassname_);
+ printer->Indent();
+ printer->Print(
+ "byte[] descriptorData = global::System.Convert.FromBase64String(\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Print("string.Concat(\n");
+ printer->Indent();
+
+ // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
+ std::string base64 = FileDescriptorToBase64(file_);
+ while (base64.size() > 60) {
+ printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60));
+ base64 = base64.substr(60);
+ }
+ printer->Print("\"$base64$\"));\n", "base64", base64);
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+
+ // -----------------------------------------------------------------
+ // Invoke InternalBuildGeneratedFileFrom() to build the file.
+ printer->Print(
+ "descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n");
+ printer->Print(" new pbr::FileDescriptor[] { ");
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ printer->Print(
+ "$full_reflection_class_name$.Descriptor, ",
+ "full_reflection_class_name",
+ GetReflectionClassName(file_->dependency(i)));
+ }
+ printer->Print("},\n"
+ " new pbr::GeneratedClrTypeInfo(");
+ // Specify all the generated code information, recursively.
+ if (file_->enum_type_count() > 0) {
+ printer->Print("new[] {");
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+ }
+ printer->Print("}, ");
+ }
+ else {
+ printer->Print("null, ");
+ }
+ if (file_->extension_count() > 0) {
+ std::vector<std::string> extensions;
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extensions.push_back(GetFullExtensionName(file_->extension(i)));
+ }
+ printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
+ }
+ else {
+ printer->Print("null, ");
+ }
+ if (file_->message_type_count() > 0) {
+ printer->Print("new pbr::GeneratedClrTypeInfo[] {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
+ }
+ printer->Outdent();
+ printer->Print("\n}));\n");
+ printer->Outdent();
+ printer->Outdent();
+ }
+ else {
+ printer->Print("null));\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("#endregion\n\n");
+}
+
+// Write out the generated code for a particular message. This consists of the CLR type, property names
+// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
+// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
+// We write a line break at the end of each generated code info, so that in the final file we'll see all
+// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
+// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
+// read even with multiple levels of nesting.
+// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
+// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
+// just controlling the formatting in the generated code.
+void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
+ if (IsMapEntryMessage(descriptor)) {
+ printer->Print("null, ");
+ return;
+ }
+ // Generated message type
+ printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor));
+
+ // Fields
+ if (descriptor->field_count() > 0) {
+ std::vector<std::string> fields;
+ fields.reserve(descriptor->field_count());
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields.push_back(GetPropertyName(descriptor->field(i)));
+ }
+ printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \""));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Oneofs
+ if (descriptor->oneof_decl_count() > 0) {
+ std::vector<std::string> oneofs;
+ oneofs.reserve(descriptor->oneof_decl_count());
+ for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
+ oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
+ }
+ printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \""));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Nested enums
+ if (descriptor->enum_type_count() > 0) {
+ std::vector<std::string> enums;
+ enums.reserve(descriptor->enum_type_count());
+ for (int i = 0; i < descriptor->enum_type_count(); i++) {
+ enums.push_back(GetClassName(descriptor->enum_type(i)));
+ }
+ printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof("));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Extensions
+ if (descriptor->extension_count() > 0) {
+ std::vector<std::string> extensions;
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ extensions.push_back(GetFullExtensionName(descriptor->extension(i)));
+ }
+ printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
+ }
+ else {
+ printer->Print("null, ");
+ }
+
+ // Nested types
+ if (descriptor->nested_type_count() > 0) {
+ // Need to specify array type explicitly here, as all elements may be null.
+ printer->Print("new pbr::GeneratedClrTypeInfo[] { ");
+ for (int i = 0; i < descriptor->nested_type_count(); i++) {
+ WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
+ }
+ printer->Print("}");
+ }
+ else {
+ printer->Print("null");
+ }
+ printer->Print(last ? ")" : "),\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.h
new file mode 100644
index 00000000..4834708b
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_reflection_class.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_source_generator_base.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class ReflectionClassGenerator : public SourceGeneratorBase {
+ public:
+ ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
+ ~ReflectionClassGenerator();
+
+ ReflectionClassGenerator(const ReflectionClassGenerator&) = delete;
+ ReflectionClassGenerator& operator=(const ReflectionClassGenerator&) = delete;
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const FileDescriptor* file_;
+
+ std::string namespace_;
+ std::string reflectionClassname_;
+ std::string extensionClassname_;
+
+ void WriteIntroduction(io::Printer* printer);
+ void WriteDescriptor(io::Printer* printer);
+ void WriteGeneratedCodeInfo(const Descriptor* descriptor,
+ io::Printer* printer,
+ bool last);
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REFLECTION_CLASS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
new file mode 100644
index 00000000..57e83266
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -0,0 +1,148 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <wire_format.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_repeated_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
+
+}
+
+void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n");
+ printer->Print(variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+ : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+ : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, "
+ "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x));\n");
+}
+
+void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.h
new file mode 100644
index 00000000..cce82868
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -0,0 +1,79 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// TODO(jonskeet): Refactor repeated field support; all the implementations are
+// *really* similar. We should probably have a RepeatedFieldGeneratorBase.
+class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~RepeatedEnumFieldGenerator();
+
+ RepeatedEnumFieldGenerator(const RepeatedEnumFieldGenerator&) = delete;
+ RepeatedEnumFieldGenerator& operator=(const RepeatedEnumFieldGenerator&) =
+ delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateFreezingCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.cc
new file mode 100644
index 00000000..bd2c22a3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -0,0 +1,174 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_repeated_message_field.h>
+#include <compiler/csharp/csharp_message_field.h>
+#include <compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
+
+}
+
+void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = ");
+ // Don't want to duplicate the codec code here... maybe we should have a
+ // "create single field generator for this repeated field"
+ // function, but it doesn't seem worth it for just this.
+ if (IsWrapperType(descriptor_)) {
+ std::unique_ptr<FieldGeneratorBase> single_generator(
+ new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options()));
+ single_generator->GenerateCodecCode(printer);
+ } else {
+ std::unique_ptr<FieldGeneratorBase> single_generator(
+ new MessageFieldGenerator(descriptor_, presenceIndex_, this->options()));
+ single_generator->GenerateCodecCode(printer);
+ }
+ printer->Print(";\n");
+ printer->Print(
+ variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+ : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+ : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) {
+ variables_["field_name"] = GetFieldName(descriptor_);
+ printer->Print(
+ variables_,
+ "PrintField(\"$field_name$\", $name$_, writer);\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void RepeatedMessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, ");
+ if (IsWrapperType(descriptor_)) {
+ std::unique_ptr<FieldGeneratorBase> single_generator(
+ new WrapperFieldGenerator(descriptor_, -1, this->options()));
+ single_generator->GenerateCodecCode(printer);
+ } else {
+ std::unique_ptr<FieldGeneratorBase> single_generator(
+ new MessageFieldGenerator(descriptor_, -1, this->options()));
+ single_generator->GenerateCodecCode(printer);
+ }
+ printer->Print(");\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.h
new file mode 100644
index 00000000..dc975888
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -0,0 +1,79 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~RepeatedMessageFieldGenerator();
+
+ RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
+ RepeatedMessageFieldGenerator& operator=(
+ const RepeatedMessageFieldGenerator&) = delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateFreezingCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
new file mode 100644
index 00000000..6df3edc5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -0,0 +1,145 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <wire_format.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_repeated_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
+
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n"
+ " = pb::FieldCodec.For$capitalized_type_name$($tag$);\n");
+ printer->Print(variables_,
+ "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
+ " get { return $name$_; }\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$name$_.Add(other.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"
+ : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+ : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "size += $name$_.CalculateSize(_repeated_$name$_codec);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "hash ^= $name$_.GetHashCode();\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if(!$name$_.Equals(other.$name$_)) return false;\n");
+}
+void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
+ printer->Print(variables_,
+ "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_ = other.$name$_.Clone();\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, pb::FieldCodec.For$capitalized_type_name$($tag$));\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
new file mode 100644
index 00000000..83bb41f2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex, const Options* options);
+ ~RepeatedPrimitiveFieldGenerator();
+
+ RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = delete;
+ RepeatedPrimitiveFieldGenerator& operator=(const RepeatedPrimitiveFieldGenerator&) = delete;
+
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateFreezingCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.cc
new file mode 100644
index 00000000..213422ad
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <compiler/csharp/csharp_source_generator_base.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_names.h>
+#include <compiler/csharp/csharp_options.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+SourceGeneratorBase::SourceGeneratorBase(
+ const Options *options) : options_(options) {
+}
+
+SourceGeneratorBase::~SourceGeneratorBase() {
+}
+
+void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
+ printer->Print("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]\n");
+ // The second argument of the [GeneratedCode] attribute could be set to current protoc
+ // version, but that would cause excessive code churn in the pre-generated
+ // code in the repository every time the protobuf version number is updated.
+ printer->Print("[global::System.CodeDom.Compiler.GeneratedCode(\"protoc\", null)]\n");
+}
+
+std::string SourceGeneratorBase::class_access_level() {
+ return this->options()->internal_access ? "internal" : "public";
+}
+
+const Options* SourceGeneratorBase::options() {
+ return this->options_;
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.h
new file mode 100644
index 00000000..b09c92b6
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class SourceGeneratorBase {
+ protected:
+ SourceGeneratorBase(const Options* options);
+ virtual ~SourceGeneratorBase();
+
+ SourceGeneratorBase(const SourceGeneratorBase&) = delete;
+ SourceGeneratorBase& operator=(const SourceGeneratorBase&) = delete;
+
+ std::string class_access_level();
+ const Options* options();
+
+ // Write any attributes used to decorate generated function members (methods and properties).
+ // Should not be used to decorate types.
+ void WriteGeneratedCodeAttributes(io::Printer* printer);
+
+ private:
+ const Options *options_;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__
+
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.cc
new file mode 100644
index 00000000..4a45017e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -0,0 +1,308 @@
+// 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 <compiler/code_generator.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <compiler/csharp/csharp_doc_comment.h>
+#include <compiler/csharp/csharp_helpers.h>
+#include <compiler/csharp/csharp_options.h>
+#include <compiler/csharp/csharp_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+ variables_["has_property_check"] = name() + "_ != null";
+ variables_["has_not_property_check"] = name() + "_ == null";
+ const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+ is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING &&
+ wrapped_field->type() != FieldDescriptor::TYPE_BYTES;
+ if (is_value_type) {
+ variables_["nonnullable_type_name"] = type_name(wrapped_field);
+ }
+}
+
+WrapperFieldGenerator::~WrapperFieldGenerator() {
+}
+
+void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = ");
+ GenerateCodecCode(printer);
+ printer->Print(
+ variables_,
+ ";\n"
+ "private $type_name$ $name$_;\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ "}\n\n");
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $name$_ != null; }\n"
+ "}\n\n");
+ printer->Print(
+ variables_,
+ "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " $name$_ = null;\n"
+ "}\n");
+ }
+}
+
+void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if (other.$has_property_check$) {\n"
+ " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n"
+ " $property_name$ = other.$property_name$;\n"
+ " }\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$type_name$ value = _single_$name$_codec.Read(ref input);\n"
+ "if ($has_not_property_check$ || value != $default_value$) {\n"
+ " $property_name$ = value;\n"
+ "}\n"
+ : "$type_name$ value = _single_$name$_codec.Read(input);\n"
+ "if ($has_not_property_check$ || value != $default_value$) {\n"
+ " $property_name$ = value;\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "if ($has_property_check$) {\n"
+ " _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n"
+ "}\n"
+ : "if ($has_property_check$) {\n"
+ " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+ "}\n");
+}
+
+void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
+ const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+ if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+ text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode($property_name$);\n";
+ }
+ else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+ text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode($property_name$);\n";
+ }
+ printer->Print(variables_, text);
+}
+
+void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
+ const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+ if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+ text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+ }
+ else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+ text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+ }
+ printer->Print(variables_, text);
+}
+
+void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
+ // TODO: Implement if we ever actually need it...
+}
+
+void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$property_name$ = other.$property_name$;\n");
+}
+
+void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+ if (is_value_type) {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)");
+ } else {
+ printer->Print(
+ variables_,
+ "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)");
+ }
+}
+
+void WrapperFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
+ WritePropertyDocComment(printer, descriptor_);
+ AddDeprecatedFlag(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
+ " new pb::Extension<$extended_type$, $type_name$>($number$, ");
+ GenerateCodecCode(printer);
+ printer->Print(");\n");
+}
+
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : WrapperFieldGenerator(descriptor, presenceIndex, options) {
+ SetCommonOneofFieldVariables(&variables_);
+}
+
+WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() {
+}
+
+void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
+ // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field.
+ printer->Print(
+ variables_,
+ "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = ");
+ GenerateCodecCode(printer);
+ printer->Print(";\n");
+ WritePropertyDocComment(printer, descriptor_);
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
+ " set {\n"
+ " $oneof_name$_ = value;\n"
+ " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+ if (SupportsPresenceApi(descriptor_)) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+ printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+ GenerateParsingCode(printer, true);
+}
+
+void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
+ printer->Print(
+ variables_,
+ use_parse_context
+ ? "$property_name$ = _oneof_$name$_codec.Read(ref input);\n"
+ : "$property_name$ = _oneof_$name$_codec.Read(input);\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+ GenerateSerializationCode(printer, true);
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+ // TODO: I suspect this is wrong...
+ printer->Print(
+ variables_,
+ use_write_context
+ ? "if ($has_property_check$) {\n"
+ " _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n"
+ "}\n"
+ : "if ($has_property_check$) {\n"
+ " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
+ "}\n");
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+ // TODO: I suspect this is wrong...
+ printer->Print(
+ variables_,
+ "if ($has_property_check$) {\n"
+ " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n"
+ "}\n");
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.h
new file mode 100644
index 00000000..86d5b7fc
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+struct Options;
+
+class WrapperFieldGenerator : public FieldGeneratorBase {
+ public:
+ WrapperFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~WrapperFieldGenerator();
+
+ WrapperFieldGenerator(const WrapperFieldGenerator&) = delete;
+ WrapperFieldGenerator& operator=(const WrapperFieldGenerator&) = delete;
+
+ virtual void GenerateCodecCode(io::Printer* printer) override;
+ virtual void GenerateCloningCode(io::Printer* printer) override;
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+ virtual void GenerateExtensionCode(io::Printer* printer) override;
+
+ virtual void WriteHash(io::Printer* printer) override;
+ virtual void WriteEquals(io::Printer* printer) override;
+ virtual void WriteToString(io::Printer* printer) override;
+
+ private:
+ bool is_value_type; // True for int32 etc; false for bytes and string
+};
+
+class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
+ public:
+ WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int presenceIndex,
+ const Options *options);
+ ~WrapperOneofFieldGenerator();
+
+ WrapperOneofFieldGenerator(const WrapperOneofFieldGenerator&) = delete;
+ WrapperOneofFieldGenerator& operator=(const WrapperOneofFieldGenerator&) = delete;
+
+ virtual void GenerateMembers(io::Printer* printer) override;
+ virtual void GenerateMergingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer) override;
+ virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context) override;
+ virtual void GenerateSerializationCode(io::Printer* printer) override;
+ virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context) override;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) override;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/importer.cc b/NorthstarDedicatedTest/include/protobuf/compiler/importer.cc
new file mode 100644
index 00000000..e2e6cd32
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/importer.cc
@@ -0,0 +1,524 @@
+// 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.
+
+#ifdef _MSC_VER
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <algorithm>
+#include <memory>
+
+#include <compiler/importer.h>
+#include <compiler/parser.h>
+#include <io/tokenizer.h>
+#include <io/zero_copy_stream_impl.h>
+#include <stubs/strutil.h>
+#include <io/io_win32.h>
+
+#ifdef _WIN32
+#include <ctype.h>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#ifdef _WIN32
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::io::win32::access;
+using google::protobuf::io::win32::open;
+#endif
+
+// Returns true if the text looks like a Windows-style absolute path, starting
+// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with
+// copy in command_line_interface.cc?
+static bool IsWindowsAbsolutePath(const std::string& text) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+ return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) &&
+ (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1;
+#else
+ return false;
+#endif
+}
+
+MultiFileErrorCollector::~MultiFileErrorCollector() {}
+
+// This class serves two purposes:
+// - It implements the ErrorCollector interface (used by Tokenizer and Parser)
+// in terms of MultiFileErrorCollector, using a particular filename.
+// - It lets us check if any errors have occurred.
+class SourceTreeDescriptorDatabase::SingleFileErrorCollector
+ : public io::ErrorCollector {
+ public:
+ SingleFileErrorCollector(const std::string& filename,
+ MultiFileErrorCollector* multi_file_error_collector)
+ : filename_(filename),
+ multi_file_error_collector_(multi_file_error_collector),
+ had_errors_(false) {}
+ ~SingleFileErrorCollector() {}
+
+ bool had_errors() { return had_errors_; }
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(int line, int column, const std::string& message) override {
+ if (multi_file_error_collector_ != NULL) {
+ multi_file_error_collector_->AddError(filename_, line, column, message);
+ }
+ had_errors_ = true;
+ }
+
+ private:
+ std::string filename_;
+ MultiFileErrorCollector* multi_file_error_collector_;
+ bool had_errors_;
+};
+
+// ===================================================================
+
+SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase(
+ SourceTree* source_tree)
+ : source_tree_(source_tree),
+ fallback_database_(nullptr),
+ error_collector_(nullptr),
+ using_validation_error_collector_(false),
+ validation_error_collector_(this) {}
+
+SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase(
+ SourceTree* source_tree, DescriptorDatabase* fallback_database)
+ : source_tree_(source_tree),
+ fallback_database_(fallback_database),
+ error_collector_(nullptr),
+ using_validation_error_collector_(false),
+ validation_error_collector_(this) {}
+
+SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {}
+
+bool SourceTreeDescriptorDatabase::FindFileByName(const std::string& filename,
+ FileDescriptorProto* output) {
+ std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
+ if (input == NULL) {
+ if (fallback_database_ != nullptr &&
+ fallback_database_->FindFileByName(filename, output)) {
+ return true;
+ }
+ if (error_collector_ != NULL) {
+ error_collector_->AddError(filename, -1, 0,
+ source_tree_->GetLastErrorMessage());
+ }
+ return false;
+ }
+
+ // Set up the tokenizer and parser.
+ SingleFileErrorCollector file_error_collector(filename, error_collector_);
+ io::Tokenizer tokenizer(input.get(), &file_error_collector);
+
+ Parser parser;
+ if (error_collector_ != NULL) {
+ parser.RecordErrorsTo(&file_error_collector);
+ }
+ if (using_validation_error_collector_) {
+ parser.RecordSourceLocationsTo(&source_locations_);
+ }
+
+ // Parse it.
+ output->set_name(filename);
+ return parser.Parse(&tokenizer, output) && !file_error_collector.had_errors();
+}
+
+bool SourceTreeDescriptorDatabase::FindFileContainingSymbol(
+ const std::string& symbol_name, FileDescriptorProto* output) {
+ return false;
+}
+
+bool SourceTreeDescriptorDatabase::FindFileContainingExtension(
+ const std::string& containing_type, int field_number,
+ FileDescriptorProto* output) {
+ return false;
+}
+
+// -------------------------------------------------------------------
+
+SourceTreeDescriptorDatabase::ValidationErrorCollector::
+ ValidationErrorCollector(SourceTreeDescriptorDatabase* owner)
+ : owner_(owner) {}
+
+SourceTreeDescriptorDatabase::ValidationErrorCollector::
+ ~ValidationErrorCollector() {}
+
+void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError(
+ const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) {
+ if (owner_->error_collector_ == NULL) return;
+
+ int line, column;
+ if (location == DescriptorPool::ErrorCollector::IMPORT) {
+ owner_->source_locations_.FindImport(descriptor, element_name, &line,
+ &column);
+ } else {
+ owner_->source_locations_.Find(descriptor, location, &line, &column);
+ }
+ owner_->error_collector_->AddError(filename, line, column, message);
+}
+
+void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning(
+ const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) {
+ if (owner_->error_collector_ == NULL) return;
+
+ int line, column;
+ if (location == DescriptorPool::ErrorCollector::IMPORT) {
+ owner_->source_locations_.FindImport(descriptor, element_name, &line,
+ &column);
+ } else {
+ owner_->source_locations_.Find(descriptor, location, &line, &column);
+ }
+ owner_->error_collector_->AddWarning(filename, line, column, message);
+}
+
+// ===================================================================
+
+Importer::Importer(SourceTree* source_tree,
+ MultiFileErrorCollector* error_collector)
+ : database_(source_tree),
+ pool_(&database_, database_.GetValidationErrorCollector()) {
+ pool_.EnforceWeakDependencies(true);
+ database_.RecordErrorsTo(error_collector);
+}
+
+Importer::~Importer() {}
+
+const FileDescriptor* Importer::Import(const std::string& filename) {
+ return pool_.FindFileByName(filename);
+}
+
+void Importer::AddUnusedImportTrackFile(const std::string& file_name,
+ bool is_error) {
+ pool_.AddUnusedImportTrackFile(file_name, is_error);
+}
+
+void Importer::ClearUnusedImportTrackFiles() {
+ pool_.ClearUnusedImportTrackFiles();
+}
+
+
+// ===================================================================
+
+SourceTree::~SourceTree() {}
+
+std::string SourceTree::GetLastErrorMessage() { return "File not found."; }
+
+DiskSourceTree::DiskSourceTree() {}
+
+DiskSourceTree::~DiskSourceTree() {}
+
+static inline char LastChar(const std::string& str) {
+ return str[str.size() - 1];
+}
+
+// Given a path, returns an equivalent path with these changes:
+// - On Windows, any backslashes are replaced with forward slashes.
+// - Any instances of the directory "." are removed.
+// - Any consecutive '/'s are collapsed into a single slash.
+// Note that the resulting string may be empty.
+//
+// TODO(kenton): It would be nice to handle "..", e.g. so that we can figure
+// out that "foo/bar.proto" is inside "baz/../foo". However, if baz is a
+// symlink or doesn't exist, then things get complicated, and we can't
+// actually determine this without investigating the filesystem, probably
+// in non-portable ways. So, we punt.
+//
+// TODO(kenton): It would be nice to use realpath() here except that it
+// resolves symbolic links. This could cause problems if people place
+// symbolic links in their source tree. For example, if you executed:
+// protoc --proto_path=foo foo/bar/baz.proto
+// then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize
+// to a path which does not appear to be under foo, and thus the compiler
+// will complain that baz.proto is not inside the --proto_path.
+static std::string CanonicalizePath(std::string path) {
+#ifdef _WIN32
+ // The Win32 API accepts forward slashes as a path delimiter even though
+ // backslashes are standard. Let's avoid confusion and use only forward
+ // slashes.
+ if (HasPrefixString(path, "\\\\")) {
+ // Avoid converting two leading backslashes.
+ path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true);
+ } else {
+ path = StringReplace(path, "\\", "/", true);
+ }
+#endif
+
+ std::vector<std::string> canonical_parts;
+ std::vector<std::string> parts = Split(
+ path, "/", true); // Note: Removes empty parts.
+ for (const std::string& part : parts) {
+ if (part == ".") {
+ // Ignore.
+ } else {
+ canonical_parts.push_back(part);
+ }
+ }
+ std::string result = Join(canonical_parts, "/");
+ if (!path.empty() && path[0] == '/') {
+ // Restore leading slash.
+ result = '/' + result;
+ }
+ if (!path.empty() && LastChar(path) == '/' && !result.empty() &&
+ LastChar(result) != '/') {
+ // Restore trailing slash.
+ result += '/';
+ }
+ return result;
+}
+
+static inline bool ContainsParentReference(const std::string& path) {
+ return path == ".." || HasPrefixString(path, "../") ||
+ HasSuffixString(path, "/..") || path.find("/../") != std::string::npos;
+}
+
+// Maps a file from an old location to a new one. Typically, old_prefix is
+// a virtual path and new_prefix is its corresponding disk path. Returns
+// false if the filename did not start with old_prefix, otherwise replaces
+// old_prefix with new_prefix and stores the result in *result. Examples:
+// string result;
+// assert(ApplyMapping("foo/bar", "", "baz", &result));
+// assert(result == "baz/foo/bar");
+//
+// assert(ApplyMapping("foo/bar", "foo", "baz", &result));
+// assert(result == "baz/bar");
+//
+// assert(ApplyMapping("foo", "foo", "bar", &result));
+// assert(result == "bar");
+//
+// assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
+// assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
+// assert(!ApplyMapping("foobar", "foo", "baz", &result));
+static bool ApplyMapping(const std::string& filename,
+ const std::string& old_prefix,
+ const std::string& new_prefix, std::string* result) {
+ if (old_prefix.empty()) {
+ // old_prefix matches any relative path.
+ if (ContainsParentReference(filename)) {
+ // We do not allow the file name to use "..".
+ return false;
+ }
+ if (HasPrefixString(filename, "/") || IsWindowsAbsolutePath(filename)) {
+ // This is an absolute path, so it isn't matched by the empty string.
+ return false;
+ }
+ result->assign(new_prefix);
+ if (!result->empty()) result->push_back('/');
+ result->append(filename);
+ return true;
+ } else if (HasPrefixString(filename, old_prefix)) {
+ // old_prefix is a prefix of the filename. Is it the whole filename?
+ if (filename.size() == old_prefix.size()) {
+ // Yep, it's an exact match.
+ *result = new_prefix;
+ return true;
+ } else {
+ // Not an exact match. Is the next character a '/'? Otherwise,
+ // this isn't actually a match at all. E.g. the prefix "foo/bar"
+ // does not match the filename "foo/barbaz".
+ int after_prefix_start = -1;
+ if (filename[old_prefix.size()] == '/') {
+ after_prefix_start = old_prefix.size() + 1;
+ } else if (filename[old_prefix.size() - 1] == '/') {
+ // old_prefix is never empty, and canonicalized paths never have
+ // consecutive '/' characters.
+ after_prefix_start = old_prefix.size();
+ }
+ if (after_prefix_start != -1) {
+ // Yep. So the prefixes are directories and the filename is a file
+ // inside them.
+ std::string after_prefix = filename.substr(after_prefix_start);
+ if (ContainsParentReference(after_prefix)) {
+ // We do not allow the file name to use "..".
+ return false;
+ }
+ result->assign(new_prefix);
+ if (!result->empty()) result->push_back('/');
+ result->append(after_prefix);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void DiskSourceTree::MapPath(const std::string& virtual_path,
+ const std::string& disk_path) {
+ mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path)));
+}
+
+DiskSourceTree::DiskFileToVirtualFileResult
+DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file,
+ std::string* virtual_file,
+ std::string* shadowing_disk_file) {
+ int mapping_index = -1;
+ std::string canonical_disk_file = CanonicalizePath(disk_file);
+
+ for (int i = 0; i < mappings_.size(); i++) {
+ // Apply the mapping in reverse.
+ if (ApplyMapping(canonical_disk_file, mappings_[i].disk_path,
+ mappings_[i].virtual_path, virtual_file)) {
+ // Success.
+ mapping_index = i;
+ break;
+ }
+ }
+
+ if (mapping_index == -1) {
+ return NO_MAPPING;
+ }
+
+ // Iterate through all mappings with higher precedence and verify that none
+ // of them map this file to some other existing file.
+ for (int i = 0; i < mapping_index; i++) {
+ if (ApplyMapping(*virtual_file, mappings_[i].virtual_path,
+ mappings_[i].disk_path, shadowing_disk_file)) {
+ if (access(shadowing_disk_file->c_str(), F_OK) >= 0) {
+ // File exists.
+ return SHADOWED;
+ }
+ }
+ }
+ shadowing_disk_file->clear();
+
+ // Verify that we can open the file. Note that this also has the side-effect
+ // of verifying that we are not canonicalizing away any non-existent
+ // directories.
+ std::unique_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
+ if (stream == NULL) {
+ return CANNOT_OPEN;
+ }
+
+ return SUCCESS;
+}
+
+bool DiskSourceTree::VirtualFileToDiskFile(const std::string& virtual_file,
+ std::string* disk_file) {
+ std::unique_ptr<io::ZeroCopyInputStream> stream(
+ OpenVirtualFile(virtual_file, disk_file));
+ return stream != NULL;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::Open(const std::string& filename) {
+ return OpenVirtualFile(filename, NULL);
+}
+
+std::string DiskSourceTree::GetLastErrorMessage() {
+ return last_error_message_;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
+ const std::string& virtual_file, std::string* disk_file) {
+ if (virtual_file != CanonicalizePath(virtual_file) ||
+ ContainsParentReference(virtual_file)) {
+ // We do not allow importing of paths containing things like ".." or
+ // consecutive slashes since the compiler expects files to be uniquely
+ // identified by file name.
+ last_error_message_ =
+ "Backslashes, consecutive slashes, \".\", or \"..\" "
+ "are not allowed in the virtual path";
+ return NULL;
+ }
+
+ for (const auto& mapping : mappings_) {
+ std::string temp_disk_file;
+ if (ApplyMapping(virtual_file, mapping.virtual_path, mapping.disk_path,
+ &temp_disk_file)) {
+ io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file);
+ if (stream != NULL) {
+ if (disk_file != NULL) {
+ *disk_file = temp_disk_file;
+ }
+ return stream;
+ }
+
+ if (errno == EACCES) {
+ // The file exists but is not readable.
+ last_error_message_ =
+ "Read access is denied for file: " + temp_disk_file;
+ return NULL;
+ }
+ }
+ }
+ last_error_message_ = "File not found.";
+ return NULL;
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
+ const std::string& filename) {
+ struct stat sb;
+ int ret = 0;
+ do {
+ ret = stat(filename.c_str(), &sb);
+ } while (ret != 0 && errno == EINTR);
+#if defined(_WIN32)
+ if (ret == 0 && sb.st_mode & S_IFDIR) {
+ last_error_message_ = "Input file is a directory.";
+ return NULL;
+ }
+#else
+ if (ret == 0 && S_ISDIR(sb.st_mode)) {
+ last_error_message_ = "Input file is a directory.";
+ return NULL;
+ }
+#endif
+ int file_descriptor;
+ do {
+ file_descriptor = open(filename.c_str(), O_RDONLY);
+ } while (file_descriptor < 0 && errno == EINTR);
+ if (file_descriptor >= 0) {
+ io::FileInputStream* result = new io::FileInputStream(file_descriptor);
+ result->SetCloseOnDelete(true);
+ return result;
+ } else {
+ return NULL;
+ }
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/importer.h b/NorthstarDedicatedTest/include/protobuf/compiler/importer.h
new file mode 100644
index 00000000..10c7feb3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/importer.h
@@ -0,0 +1,336 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file is the public interface to the .proto file parser.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
+#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
+
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+#include <compiler/parser.h>
+#include <descriptor.h>
+#include <descriptor_database.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class ZeroCopyInputStream;
+}
+
+namespace compiler {
+
+// Defined in this file.
+class Importer;
+class MultiFileErrorCollector;
+class SourceTree;
+class DiskSourceTree;
+
+// TODO(kenton): Move all SourceTree stuff to a separate file?
+
+// An implementation of DescriptorDatabase which loads files from a SourceTree
+// and parses them.
+//
+// Note: This class is not thread-safe since it maintains a table of source
+// code locations for error reporting. However, when a DescriptorPool wraps
+// a DescriptorDatabase, it uses mutex locking to make sure only one method
+// of the database is called at a time, even if the DescriptorPool is used
+// from multiple threads. Therefore, there is only a problem if you create
+// multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase
+// and use them from multiple threads.
+//
+// Note: This class does not implement FindFileContainingSymbol() or
+// FindFileContainingExtension(); these will always return false.
+class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase {
+ public:
+ SourceTreeDescriptorDatabase(SourceTree* source_tree);
+
+ // If non-NULL, fallback_database will be checked if a file doesn't exist in
+ // the specified source_tree.
+ SourceTreeDescriptorDatabase(SourceTree* source_tree,
+ DescriptorDatabase* fallback_database);
+ ~SourceTreeDescriptorDatabase();
+
+ // Instructs the SourceTreeDescriptorDatabase to report any parse errors
+ // to the given MultiFileErrorCollector. This should be called before
+ // parsing. error_collector must remain valid until either this method
+ // is called again or the SourceTreeDescriptorDatabase is destroyed.
+ void RecordErrorsTo(MultiFileErrorCollector* error_collector) {
+ error_collector_ = error_collector;
+ }
+
+ // Gets a DescriptorPool::ErrorCollector which records errors to the
+ // MultiFileErrorCollector specified with RecordErrorsTo(). This collector
+ // has the ability to determine exact line and column numbers of errors
+ // from the information given to it by the DescriptorPool.
+ DescriptorPool::ErrorCollector* GetValidationErrorCollector() {
+ using_validation_error_collector_ = true;
+ return &validation_error_collector_;
+ }
+
+ // implements DescriptorDatabase -----------------------------------
+ bool FindFileByName(const std::string& filename,
+ FileDescriptorProto* output) override;
+ bool FindFileContainingSymbol(const std::string& symbol_name,
+ FileDescriptorProto* output) override;
+ bool FindFileContainingExtension(const std::string& containing_type,
+ int field_number,
+ FileDescriptorProto* output) override;
+
+ private:
+ class SingleFileErrorCollector;
+
+ SourceTree* source_tree_;
+ DescriptorDatabase* fallback_database_;
+ MultiFileErrorCollector* error_collector_;
+
+ class PROTOBUF_EXPORT ValidationErrorCollector
+ : public DescriptorPool::ErrorCollector {
+ public:
+ ValidationErrorCollector(SourceTreeDescriptorDatabase* owner);
+ ~ValidationErrorCollector();
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) override;
+
+ void AddWarning(const std::string& filename,
+ const std::string& element_name, const Message* descriptor,
+ ErrorLocation location,
+ const std::string& message) override;
+
+ private:
+ SourceTreeDescriptorDatabase* owner_;
+ };
+ friend class ValidationErrorCollector;
+
+ bool using_validation_error_collector_;
+ SourceLocationTable source_locations_;
+ ValidationErrorCollector validation_error_collector_;
+};
+
+// Simple interface for parsing .proto files. This wraps the process
+// of opening the file, parsing it with a Parser, recursively parsing all its
+// imports, and then cross-linking the results to produce a FileDescriptor.
+//
+// This is really just a thin wrapper around SourceTreeDescriptorDatabase.
+// You may find that SourceTreeDescriptorDatabase is more flexible.
+//
+// TODO(kenton): I feel like this class is not well-named.
+class PROTOBUF_EXPORT Importer {
+ public:
+ Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector);
+ ~Importer();
+
+ // Import the given file and build a FileDescriptor representing it. If
+ // the file is already in the DescriptorPool, the existing FileDescriptor
+ // will be returned. The FileDescriptor is property of the DescriptorPool,
+ // and will remain valid until it is destroyed. If any errors occur, they
+ // will be reported using the error collector and Import() will return NULL.
+ //
+ // A particular Importer object will only report errors for a particular
+ // file once. All future attempts to import the same file will return NULL
+ // without reporting any errors. The idea is that you might want to import
+ // a lot of files without seeing the same errors over and over again. If
+ // you want to see errors for the same files repeatedly, you can use a
+ // separate Importer object to import each one (but use the same
+ // DescriptorPool so that they can be cross-linked).
+ const FileDescriptor* Import(const std::string& filename);
+
+ // The DescriptorPool in which all imported FileDescriptors and their
+ // contents are stored.
+ inline const DescriptorPool* pool() const { return &pool_; }
+
+ void AddUnusedImportTrackFile(const std::string& file_name,
+ bool is_error = false);
+ void ClearUnusedImportTrackFiles();
+
+
+ private:
+ SourceTreeDescriptorDatabase database_;
+ DescriptorPool pool_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
+};
+
+// If the importer encounters problems while trying to import the proto files,
+// it reports them to a MultiFileErrorCollector.
+class PROTOBUF_EXPORT MultiFileErrorCollector {
+ public:
+ inline MultiFileErrorCollector() {}
+ virtual ~MultiFileErrorCollector();
+
+ // Line and column numbers are zero-based. A line number of -1 indicates
+ // an error with the entire file (e.g. "not found").
+ virtual void AddError(const std::string& filename, int line, int column,
+ const std::string& message) = 0;
+
+ virtual void AddWarning(const std::string& /* filename */, int /* line */,
+ int /* column */, const std::string& /* message */) {}
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
+};
+
+// Abstract interface which represents a directory tree containing proto files.
+// Used by the default implementation of Importer to resolve import statements
+// Most users will probably want to use the DiskSourceTree implementation,
+// below.
+class PROTOBUF_EXPORT SourceTree {
+ public:
+ inline SourceTree() {}
+ virtual ~SourceTree();
+
+ // Open the given file and return a stream that reads it, or NULL if not
+ // found. The caller takes ownership of the returned object. The filename
+ // must be a path relative to the root of the source tree and must not
+ // contain "." or ".." components.
+ virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0;
+
+ // If Open() returns NULL, calling this method immediately will return an
+ // description of the error.
+ // Subclasses should implement this method and return a meaningful value for
+ // better error reporting.
+ // TODO(xiaofeng): change this to a pure virtual function.
+ virtual std::string GetLastErrorMessage();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
+};
+
+// An implementation of SourceTree which loads files from locations on disk.
+// Multiple mappings can be set up to map locations in the DiskSourceTree to
+// locations in the physical filesystem.
+class PROTOBUF_EXPORT DiskSourceTree : public SourceTree {
+ public:
+ DiskSourceTree();
+ ~DiskSourceTree();
+
+ // Map a path on disk to a location in the SourceTree. The path may be
+ // either a file or a directory. If it is a directory, the entire tree
+ // under it will be mapped to the given virtual location. To map a directory
+ // to the root of the source tree, pass an empty string for virtual_path.
+ //
+ // If multiple mapped paths apply when opening a file, they will be searched
+ // in order. For example, if you do:
+ // MapPath("bar", "foo/bar");
+ // MapPath("", "baz");
+ // and then you do:
+ // Open("bar/qux");
+ // the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux,
+ // returning the first one that opens successfully.
+ //
+ // disk_path may be an absolute path or relative to the current directory,
+ // just like a path you'd pass to open().
+ void MapPath(const std::string& virtual_path, const std::string& disk_path);
+
+ // Return type for DiskFileToVirtualFile().
+ enum DiskFileToVirtualFileResult {
+ SUCCESS,
+ SHADOWED,
+ CANNOT_OPEN,
+ NO_MAPPING
+ };
+
+ // Given a path to a file on disk, find a virtual path mapping to that
+ // file. The first mapping created with MapPath() whose disk_path contains
+ // the filename is used. However, that virtual path may not actually be
+ // usable to open the given file. Possible return values are:
+ // * SUCCESS: The mapping was found. *virtual_file is filled in so that
+ // calling Open(*virtual_file) will open the file named by disk_file.
+ // * SHADOWED: A mapping was found, but using Open() to open this virtual
+ // path will end up returning some different file. This is because some
+ // other mapping with a higher precedence also matches this virtual path
+ // and maps it to a different file that exists on disk. *virtual_file
+ // is filled in as it would be in the SUCCESS case. *shadowing_disk_file
+ // is filled in with the disk path of the file which would be opened if
+ // you were to call Open(*virtual_file).
+ // * CANNOT_OPEN: The mapping was found and was not shadowed, but the
+ // file specified cannot be opened. When this value is returned,
+ // errno will indicate the reason the file cannot be opened. *virtual_file
+ // will be set to the virtual path as in the SUCCESS case, even though
+ // it is not useful.
+ // * NO_MAPPING: Indicates that no mapping was found which contains this
+ // file.
+ DiskFileToVirtualFileResult DiskFileToVirtualFile(
+ const std::string& disk_file, std::string* virtual_file,
+ std::string* shadowing_disk_file);
+
+ // Given a virtual path, find the path to the file on disk.
+ // Return true and update disk_file with the on-disk path if the file exists.
+ // Return false and leave disk_file untouched if the file doesn't exist.
+ bool VirtualFileToDiskFile(const std::string& virtual_file,
+ std::string* disk_file);
+
+ // implements SourceTree -------------------------------------------
+ io::ZeroCopyInputStream* Open(const std::string& filename) override;
+
+ std::string GetLastErrorMessage() override;
+
+ private:
+ struct Mapping {
+ std::string virtual_path;
+ std::string disk_path;
+
+ inline Mapping(const std::string& virtual_path_param,
+ const std::string& disk_path_param)
+ : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
+ };
+ std::vector<Mapping> mappings_;
+ std::string last_error_message_;
+
+ // Like Open(), but returns the on-disk path in disk_file if disk_file is
+ // non-NULL and the file could be successfully opened.
+ io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file,
+ std::string* disk_file);
+
+ // Like Open() but given the actual on-disk path.
+ io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/importer_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/importer_unittest.cc
new file mode 100644
index 00000000..16ff90f2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/importer_unittest.cc
@@ -0,0 +1,548 @@
+// 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 <compiler/importer.h>
+
+#include <memory>
+#include <unordered_map>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <stubs/substitute.h>
+#include <stubs/map_util.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+bool FileExists(const std::string& path) {
+ return File::Exists(path);
+}
+
+#define EXPECT_SUBSTRING(needle, haystack) \
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, (needle), (haystack))
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+ MockErrorCollector() {}
+ ~MockErrorCollector() {}
+
+ std::string text_;
+ std::string warning_text_;
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, int line, int column,
+ const std::string& message) {
+ strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+ message);
+ }
+
+ void AddWarning(const std::string& filename, int line, int column,
+ const std::string& message) {
+ strings::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n", filename, line,
+ column, message);
+ }
+};
+
+// -------------------------------------------------------------------
+
+// A dummy implementation of SourceTree backed by a simple map.
+class MockSourceTree : public SourceTree {
+ public:
+ MockSourceTree() {}
+ ~MockSourceTree() {}
+
+ void AddFile(const std::string& name, const char* contents) {
+ files_[name] = contents;
+ }
+
+ // implements SourceTree -------------------------------------------
+ io::ZeroCopyInputStream* Open(const std::string& filename) {
+ const char* contents = FindPtrOrNull(files_, filename);
+ if (contents == NULL) {
+ return NULL;
+ } else {
+ return new io::ArrayInputStream(contents, strlen(contents));
+ }
+ }
+
+ std::string GetLastErrorMessage() { return "File not found."; }
+
+ private:
+ std::unordered_map<std::string, const char*> files_;
+};
+
+// ===================================================================
+
+class ImporterTest : public testing::Test {
+ protected:
+ ImporterTest() : importer_(&source_tree_, &error_collector_) {}
+
+ void AddFile(const std::string& filename, const char* text) {
+ source_tree_.AddFile(filename, text);
+ }
+
+ // Return the collected error text
+ std::string warning() const { return error_collector_.warning_text_; }
+
+ MockErrorCollector error_collector_;
+ MockSourceTree source_tree_;
+ Importer importer_;
+};
+
+TEST_F(ImporterTest, Import) {
+ // Test normal importing.
+ AddFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ const FileDescriptor* file = importer_.Import("foo.proto");
+ EXPECT_EQ("", error_collector_.text_);
+ ASSERT_TRUE(file != NULL);
+
+ ASSERT_EQ(1, file->message_type_count());
+ EXPECT_EQ("Foo", file->message_type(0)->name());
+
+ // Importing again should return same object.
+ EXPECT_EQ(file, importer_.Import("foo.proto"));
+}
+
+TEST_F(ImporterTest, ImportNested) {
+ // Test that importing a file which imports another file works.
+ AddFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo {\n"
+ " optional Bar bar = 1;\n"
+ "}\n");
+ AddFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar {}\n");
+
+ // Note that both files are actually parsed by the first call to Import()
+ // here, since foo.proto imports bar.proto. The second call just returns
+ // the same ProtoFile for bar.proto which was constructed while importing
+ // foo.proto. We test that this is the case below by checking that bar
+ // is among foo's dependencies (by pointer).
+ const FileDescriptor* foo = importer_.Import("foo.proto");
+ const FileDescriptor* bar = importer_.Import("bar.proto");
+ EXPECT_EQ("", error_collector_.text_);
+ ASSERT_TRUE(foo != NULL);
+ ASSERT_TRUE(bar != NULL);
+
+ // Check that foo's dependency is the same object as bar.
+ ASSERT_EQ(1, foo->dependency_count());
+ EXPECT_EQ(bar, foo->dependency(0));
+
+ // Check that foo properly cross-links bar.
+ ASSERT_EQ(1, foo->message_type_count());
+ ASSERT_EQ(1, bar->message_type_count());
+ ASSERT_EQ(1, foo->message_type(0)->field_count());
+ ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE,
+ foo->message_type(0)->field(0)->type());
+ EXPECT_EQ(bar->message_type(0),
+ foo->message_type(0)->field(0)->message_type());
+}
+
+TEST_F(ImporterTest, FileNotFound) {
+ // Error: Parsing a file that doesn't exist.
+ EXPECT_TRUE(importer_.Import("foo.proto") == NULL);
+ EXPECT_EQ("foo.proto:-1:0: File not found.\n", error_collector_.text_);
+}
+
+TEST_F(ImporterTest, ImportNotFound) {
+ // Error: Importing a file that doesn't exist.
+ AddFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n");
+
+ EXPECT_TRUE(importer_.Import("foo.proto") == NULL);
+ EXPECT_EQ(
+ "bar.proto:-1:0: File not found.\n"
+ "foo.proto:1:0: Import \"bar.proto\" was not found or had errors.\n",
+ error_collector_.text_);
+}
+
+TEST_F(ImporterTest, RecursiveImport) {
+ // Error: Recursive import.
+ AddFile("recursive1.proto",
+ "syntax = \"proto2\";\n"
+ "\n"
+ "import \"recursive2.proto\";\n");
+ AddFile("recursive2.proto",
+ "syntax = \"proto2\";\n"
+ "import \"recursive1.proto\";\n");
+
+ EXPECT_TRUE(importer_.Import("recursive1.proto") == NULL);
+ EXPECT_EQ(
+ "recursive1.proto:2:0: File recursively imports itself: "
+ "recursive1.proto "
+ "-> recursive2.proto -> recursive1.proto\n"
+ "recursive2.proto:1:0: Import \"recursive1.proto\" was not found "
+ "or had errors.\n"
+ "recursive1.proto:2:0: Import \"recursive2.proto\" was not found "
+ "or had errors.\n",
+ error_collector_.text_);
+}
+
+TEST_F(ImporterTest, RecursiveImportSelf) {
+ // Error: Recursive import.
+ AddFile("recursive.proto",
+ "syntax = \"proto2\";\n"
+ "\n"
+ "import \"recursive.proto\";\n");
+
+ EXPECT_TRUE(importer_.Import("recursive.proto") == nullptr);
+ EXPECT_EQ(
+ "recursive.proto:2:0: File recursively imports itself: "
+ "recursive.proto -> recursive.proto\n",
+ error_collector_.text_);
+}
+
+TEST_F(ImporterTest, LiteRuntimeImport) {
+ // Error: Recursive import.
+ AddFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "option optimize_for = LITE_RUNTIME;\n");
+ AddFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n");
+
+ EXPECT_TRUE(importer_.Import("foo.proto") == nullptr);
+ EXPECT_EQ(
+ "foo.proto:1:0: Files that do not use optimize_for = LITE_RUNTIME "
+ "cannot import files which do use this option. This file is not "
+ "lite, but it imports \"bar.proto\" which is.\n",
+ error_collector_.text_);
+}
+
+
+// ===================================================================
+
+class DiskSourceTreeTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_1");
+ dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_2");
+
+ for (int i = 0; i < dirnames_.size(); i++) {
+ if (FileExists(dirnames_[i])) {
+ File::DeleteRecursively(dirnames_[i], NULL, NULL);
+ }
+ GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777));
+ }
+ }
+
+ virtual void TearDown() {
+ for (int i = 0; i < dirnames_.size(); i++) {
+ if (FileExists(dirnames_[i])) {
+ File::DeleteRecursively(dirnames_[i], NULL, NULL);
+ }
+ }
+ }
+
+ void AddFile(const std::string& filename, const char* contents) {
+ GOOGLE_CHECK_OK(File::SetContents(filename, contents, true));
+ }
+
+ void AddSubdir(const std::string& dirname) {
+ GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777));
+ }
+
+ void ExpectFileContents(const std::string& filename,
+ const char* expected_contents) {
+ std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+
+ ASSERT_FALSE(input == NULL);
+
+ // Read all the data from the file.
+ std::string file_contents;
+ const void* data;
+ int size;
+ while (input->Next(&data, &size)) {
+ file_contents.append(reinterpret_cast<const char*>(data), size);
+ }
+
+ EXPECT_EQ(expected_contents, file_contents);
+ }
+
+ void ExpectCannotOpenFile(const std::string& filename,
+ const std::string& error_message) {
+ std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+ EXPECT_TRUE(input == NULL);
+ EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
+ }
+
+ DiskSourceTree source_tree_;
+
+ // Paths of two on-disk directories to use during the test.
+ std::vector<std::string> dirnames_;
+};
+
+TEST_F(DiskSourceTreeTest, MapRoot) {
+ // Test opening a file in a directory that is mapped to the root of the
+ // source tree.
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ source_tree_.MapPath("", dirnames_[0]);
+
+ ExpectFileContents("foo", "Hello World!");
+ ExpectCannotOpenFile("bar", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, MapDirectory) {
+ // Test opening a file in a directory that is mapped to somewhere other
+ // than the root of the source tree.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ source_tree_.MapPath("baz", dirnames_[0]);
+
+ ExpectFileContents("baz/foo", "Hello World!");
+ ExpectCannotOpenFile("baz/bar", "File not found.");
+ ExpectCannotOpenFile("foo", "File not found.");
+ ExpectCannotOpenFile("bar", "File not found.");
+
+ // Non-canonical file names should not work.
+ ExpectCannotOpenFile("baz//foo",
+ "Backslashes, consecutive slashes, \".\", or \"..\" are "
+ "not allowed in the virtual path");
+ ExpectCannotOpenFile("baz/../baz/foo",
+ "Backslashes, consecutive slashes, \".\", or \"..\" are "
+ "not allowed in the virtual path");
+ ExpectCannotOpenFile("baz/./foo",
+ "Backslashes, consecutive slashes, \".\", or \"..\" are "
+ "not allowed in the virtual path");
+ ExpectCannotOpenFile("baz/foo/", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, NoParent) {
+ // Test that we cannot open files in a parent of a mapped directory.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ AddSubdir(dirnames_[0] + "/bar");
+ AddFile(dirnames_[0] + "/bar/baz", "Blah.");
+ source_tree_.MapPath("", dirnames_[0] + "/bar");
+
+ ExpectFileContents("baz", "Blah.");
+ ExpectCannotOpenFile("../foo",
+ "Backslashes, consecutive slashes, \".\", or \"..\" are "
+ "not allowed in the virtual path");
+ ExpectCannotOpenFile("../bar/baz",
+ "Backslashes, consecutive slashes, \".\", or \"..\" are "
+ "not allowed in the virtual path");
+}
+
+TEST_F(DiskSourceTreeTest, MapFile) {
+ // Test opening a file that is mapped directly into the source tree.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ source_tree_.MapPath("foo", dirnames_[0] + "/foo");
+
+ ExpectFileContents("foo", "Hello World!");
+ ExpectCannotOpenFile("bar", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) {
+ // Test mapping and searching multiple directories.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+ AddFile(dirnames_[1] + "/bar", "Goodbye World!");
+ source_tree_.MapPath("", dirnames_[0]);
+ source_tree_.MapPath("", dirnames_[1]);
+
+ ExpectFileContents("foo", "Hello World!");
+ ExpectFileContents("bar", "Goodbye World!");
+ ExpectCannotOpenFile("baz", "File not found.");
+}
+
+TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) {
+ // Test that directories are always searched in order, even when a latter
+ // directory is more-specific than a former one.
+
+ // Create the "bar" directory so we can put a file in it.
+ GOOGLE_CHECK_OK(File::CreateDir(dirnames_[0] + "/bar", 0777));
+
+ // Add files and map paths.
+ AddFile(dirnames_[0] + "/bar/foo", "Hello World!");
+ AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+ source_tree_.MapPath("", dirnames_[0]);
+ source_tree_.MapPath("bar", dirnames_[1]);
+
+ // Check.
+ ExpectFileContents("bar/foo", "Hello World!");
+}
+
+TEST_F(DiskSourceTreeTest, DiskFileToVirtualFile) {
+ // Test DiskFileToVirtualFile.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+ source_tree_.MapPath("bar", dirnames_[0]);
+ source_tree_.MapPath("bar", dirnames_[1]);
+
+ std::string virtual_file;
+ std::string shadowing_disk_file;
+
+ EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+ source_tree_.DiskFileToVirtualFile("/foo", &virtual_file,
+ &shadowing_disk_file));
+
+ EXPECT_EQ(DiskSourceTree::SHADOWED,
+ source_tree_.DiskFileToVirtualFile(
+ dirnames_[1] + "/foo", &virtual_file, &shadowing_disk_file));
+ EXPECT_EQ("bar/foo", virtual_file);
+ EXPECT_EQ(dirnames_[0] + "/foo", shadowing_disk_file);
+
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile(
+ dirnames_[1] + "/baz", &virtual_file, &shadowing_disk_file));
+ EXPECT_EQ("bar/baz", virtual_file);
+
+ EXPECT_EQ(DiskSourceTree::SUCCESS,
+ source_tree_.DiskFileToVirtualFile(
+ dirnames_[0] + "/foo", &virtual_file, &shadowing_disk_file));
+ EXPECT_EQ("bar/foo", virtual_file);
+}
+
+TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) {
+ // Test handling of "..", ".", etc. in DiskFileToVirtualFile().
+
+ source_tree_.MapPath("dir1", "..");
+ source_tree_.MapPath("dir2", "../../foo");
+ source_tree_.MapPath("dir3", "./foo/bar/.");
+ source_tree_.MapPath("dir4", ".");
+ source_tree_.MapPath("", "/qux");
+ source_tree_.MapPath("dir5", "/quux/");
+
+ std::string virtual_file;
+ std::string shadowing_disk_file;
+
+ // "../.." should not be considered to be under "..".
+ EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+ source_tree_.DiskFileToVirtualFile("../../baz", &virtual_file,
+ &shadowing_disk_file));
+
+ // "/foo" is not mapped (it should not be misinterpreted as being under ".").
+ EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+ source_tree_.DiskFileToVirtualFile("/foo", &virtual_file,
+ &shadowing_disk_file));
+
+#ifdef WIN32
+ // "C:\foo" is not mapped (it should not be misinterpreted as being under
+ // ".").
+ EXPECT_EQ(DiskSourceTree::NO_MAPPING,
+ source_tree_.DiskFileToVirtualFile("C:\\foo", &virtual_file,
+ &shadowing_disk_file));
+#endif // WIN32
+
+ // But "../baz" should be.
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("../baz", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("dir1/baz", virtual_file);
+
+ // "../../foo/baz" is under "../../foo".
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("../../foo/baz", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("dir2/baz", virtual_file);
+
+ // "foo/./bar/baz" is under "./foo/bar/.".
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("foo/bar/baz", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("dir3/baz", virtual_file);
+
+ // "bar" is under ".".
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("bar", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("dir4/bar", virtual_file);
+
+ // "/qux/baz" is under "/qux".
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("/qux/baz", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("baz", virtual_file);
+
+ // "/quux/bar" is under "/quux".
+ EXPECT_EQ(DiskSourceTree::CANNOT_OPEN,
+ source_tree_.DiskFileToVirtualFile("/quux/bar", &virtual_file,
+ &shadowing_disk_file));
+ EXPECT_EQ("dir5/bar", virtual_file);
+}
+
+TEST_F(DiskSourceTreeTest, VirtualFileToDiskFile) {
+ // Test VirtualFileToDiskFile.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+ AddFile(dirnames_[1] + "/quux", "This file should not be hidden.");
+ source_tree_.MapPath("bar", dirnames_[0]);
+ source_tree_.MapPath("bar", dirnames_[1]);
+
+ // Existent files, shadowed and non-shadowed case.
+ std::string disk_file;
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", &disk_file));
+ EXPECT_EQ(dirnames_[0] + "/foo", disk_file);
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/quux", &disk_file));
+ EXPECT_EQ(dirnames_[1] + "/quux", disk_file);
+
+ // Nonexistent file in existent directory and vice versa.
+ std::string not_touched = "not touched";
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("bar/baz", &not_touched));
+ EXPECT_EQ("not touched", not_touched);
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", &not_touched));
+ EXPECT_EQ("not touched", not_touched);
+
+ // Accept NULL as output parameter.
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", NULL));
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", NULL));
+}
+
+} // namespace
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.cc
new file mode 100644
index 00000000..00ffc946
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.cc
@@ -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.
+
+#include <compiler/java/java_context.h>
+
+#include <compiler/java/java_field.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.h>
+#include <stubs/strutil.h>
+#include <stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+Context::Context(const FileDescriptor* file, const Options& options)
+ : name_resolver_(new ClassNameResolver), options_(options) {
+ InitializeFieldGeneratorInfo(file);
+}
+
+Context::~Context() {}
+
+ClassNameResolver* Context::GetNameResolver() const {
+ return name_resolver_.get();
+}
+
+namespace {
+// Whether two fields have conflicting accessors (assuming name1 and name2
+// are different). name1 and name2 are field1 and field2's camel-case name
+// respectively.
+bool IsConflicting(const FieldDescriptor* field1, const std::string& name1,
+ const FieldDescriptor* field2, const std::string& name2,
+ std::string* info) {
+ if (field1->is_repeated()) {
+ if (field2->is_repeated()) {
+ // Both fields are repeated.
+ return false;
+ } else {
+ // field1 is repeated, and field2 is not.
+ if (name1 + "Count" == name2) {
+ *info = "both repeated field \"" + field1->name() + "\" and singular " +
+ "field \"" + field2->name() + "\" generate the method \"" +
+ "get" + name1 + "Count()\"";
+ return true;
+ }
+ if (name1 + "List" == name2) {
+ *info = "both repeated field \"" + field1->name() + "\" and singular " +
+ "field \"" + field2->name() + "\" generate the method \"" +
+ "get" + name1 + "List()\"";
+ return true;
+ }
+ // Well, there are obviously many more conflicting cases, but it probably
+ // doesn't worth the effort to exhaust all of them because they rarely
+ // happen and as we are continuing adding new methods/changing existing
+ // methods the number of different conflicting cases will keep growing.
+ // We can just add more cases here when they are found in the real world.
+ return false;
+ }
+ } else {
+ if (field2->is_repeated()) {
+ return IsConflicting(field2, name2, field1, name1, info);
+ } else {
+ // None of the two fields are repeated.
+ return false;
+ }
+ }
+}
+} // namespace
+
+void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) {
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ InitializeFieldGeneratorInfoForMessage(file->message_type(i));
+ }
+}
+
+void Context::InitializeFieldGeneratorInfoForMessage(
+ const Descriptor* message) {
+ for (int i = 0; i < message->nested_type_count(); ++i) {
+ InitializeFieldGeneratorInfoForMessage(message->nested_type(i));
+ }
+ std::vector<const FieldDescriptor*> fields;
+ fields.reserve(message->field_count());
+ for (int i = 0; i < message->field_count(); ++i) {
+ fields.push_back(message->field(i));
+ }
+ InitializeFieldGeneratorInfoForFields(fields);
+
+ for (int i = 0; i < message->oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ OneofGeneratorInfo info;
+ info.name = UnderscoresToCamelCase(oneof->name(), false);
+ info.capitalized_name = UnderscoresToCamelCase(oneof->name(), true);
+ oneof_generator_info_map_[oneof] = info;
+ }
+}
+
+void Context::InitializeFieldGeneratorInfoForFields(
+ const std::vector<const FieldDescriptor*>& fields) {
+ // Find out all fields that conflict with some other field in the same
+ // message.
+ std::vector<bool> is_conflict(fields.size());
+ std::vector<std::string> conflict_reason(fields.size());
+ for (int i = 0; i < fields.size(); ++i) {
+ const FieldDescriptor* field = fields[i];
+ const std::string& name = UnderscoresToCapitalizedCamelCase(field);
+ for (int j = i + 1; j < fields.size(); ++j) {
+ const FieldDescriptor* other = fields[j];
+ const std::string& other_name = UnderscoresToCapitalizedCamelCase(other);
+ if (name == other_name) {
+ is_conflict[i] = is_conflict[j] = true;
+ conflict_reason[i] = conflict_reason[j] =
+ "capitalized name of field \"" + field->name() +
+ "\" conflicts with field \"" + other->name() + "\"";
+ } else if (IsConflicting(field, name, other, other_name,
+ &conflict_reason[j])) {
+ is_conflict[i] = is_conflict[j] = true;
+ conflict_reason[i] = conflict_reason[j];
+ }
+ }
+ if (is_conflict[i]) {
+ GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting "
+ << "with another field: " << conflict_reason[i];
+ }
+ }
+ for (int i = 0; i < fields.size(); ++i) {
+ const FieldDescriptor* field = fields[i];
+ FieldGeneratorInfo info;
+ info.name = CamelCaseFieldName(field);
+ info.capitalized_name = UnderscoresToCapitalizedCamelCase(field);
+ // For fields conflicting with some other fields, we append the field
+ // number to their field names in generated code to avoid conflicts.
+ if (is_conflict[i]) {
+ info.name += StrCat(field->number());
+ info.capitalized_name += StrCat(field->number());
+ info.disambiguated_reason = conflict_reason[i];
+ }
+ field_generator_info_map_[field] = info;
+ }
+}
+
+const FieldGeneratorInfo* Context::GetFieldGeneratorInfo(
+ const FieldDescriptor* field) const {
+ const FieldGeneratorInfo* result =
+ FindOrNull(field_generator_info_map_, field);
+ if (result == NULL) {
+ GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: "
+ << field->full_name();
+ }
+ return result;
+}
+
+const OneofGeneratorInfo* Context::GetOneofGeneratorInfo(
+ const OneofDescriptor* oneof) const {
+ const OneofGeneratorInfo* result =
+ FindOrNull(oneof_generator_info_map_, oneof);
+ if (result == NULL) {
+ GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: "
+ << oneof->name();
+ }
+ return result;
+}
+
+// Does this message class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+bool Context::HasGeneratedMethods(const Descriptor* descriptor) const {
+ return options_.enforce_lite ||
+ descriptor->file()->options().optimize_for() != FileOptions::CODE_SIZE;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.h
new file mode 100644
index 00000000..ed6e9e9c
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_context.h
@@ -0,0 +1,113 @@
+// 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_JAVA_CONTEXT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <stubs/common.h>
+#include <compiler/java/java_options.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor;
+class FieldDescriptor;
+class OneofDescriptor;
+class Descriptor;
+class EnumDescriptor;
+namespace compiler {
+namespace java {
+class ClassNameResolver; // name_resolver.h
+}
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+struct FieldGeneratorInfo;
+struct OneofGeneratorInfo;
+// A context object holds the information that is shared among all code
+// generators.
+class Context {
+ public:
+ Context(const FileDescriptor* file, const Options& options);
+ ~Context();
+
+ // Get the name resolver associated with this context. The resolver
+ // can be used to map descriptors to Java class names.
+ ClassNameResolver* GetNameResolver() const;
+
+ // Get the FieldGeneratorInfo for a given field.
+ const FieldGeneratorInfo* GetFieldGeneratorInfo(
+ const FieldDescriptor* field) const;
+
+ // Get the OneofGeneratorInfo for a given oneof.
+ const OneofGeneratorInfo* GetOneofGeneratorInfo(
+ const OneofDescriptor* oneof) const;
+
+ const Options& options() const { return options_; }
+
+ // Enforces all the files (including transitive dependencies) to use
+ // LiteRuntime.
+
+ bool EnforceLite() const { return options_.enforce_lite; }
+
+ // Does this message class have generated parsing, serialization, and other
+ // standard methods for which reflection-based fallback implementations exist?
+ bool HasGeneratedMethods(const Descriptor* descriptor) const;
+
+ private:
+ void InitializeFieldGeneratorInfo(const FileDescriptor* file);
+ void InitializeFieldGeneratorInfoForMessage(const Descriptor* message);
+ void InitializeFieldGeneratorInfoForFields(
+ const std::vector<const FieldDescriptor*>& fields);
+
+ std::unique_ptr<ClassNameResolver> name_resolver_;
+ std::map<const FieldDescriptor*, FieldGeneratorInfo>
+ field_generator_info_map_;
+ std::map<const OneofDescriptor*, OneofGeneratorInfo>
+ oneof_generator_info_map_;
+ Options options_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.cc
new file mode 100644
index 00000000..ed9f0d27
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.cc
@@ -0,0 +1,435 @@
+// 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 <compiler/java/java_doc_comment.h>
+
+#include <vector>
+
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+std::string EscapeJavadoc(const std::string& input) {
+ std::string result;
+ result.reserve(input.size() * 2);
+
+ char prev = '*';
+
+ for (std::string::size_type i = 0; i < input.size(); i++) {
+ char c = input[i];
+ switch (c) {
+ case '*':
+ // Avoid "/*".
+ if (prev == '/') {
+ result.append("&#42;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '/':
+ // Avoid "*/".
+ if (prev == '*') {
+ result.append("&#47;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '@':
+ // '@' starts javadoc tags including the @deprecated tag, which will
+ // cause a compile-time error if inserted before a declaration that
+ // does not have a corresponding @Deprecated annotation.
+ result.append("&#64;");
+ break;
+ case '<':
+ // Avoid interpretation as HTML.
+ result.append("&lt;");
+ break;
+ case '>':
+ // Avoid interpretation as HTML.
+ result.append("&gt;");
+ break;
+ case '&':
+ // Avoid interpretation as HTML.
+ result.append("&amp;");
+ break;
+ case '\\':
+ // Java interprets Unicode escape sequences anywhere!
+ result.append("&#92;");
+ break;
+ default:
+ result.push_back(c);
+ break;
+ }
+
+ prev = c;
+ }
+
+ return result;
+}
+
+static void WriteDocCommentBodyForLocation(io::Printer* printer,
+ const SourceLocation& location) {
+ std::string comments = location.leading_comments.empty()
+ ? location.trailing_comments
+ : location.leading_comments;
+ if (!comments.empty()) {
+ // TODO(kenton): Ideally we should parse the comment text as Markdown and
+ // write it back as HTML, but this requires a Markdown parser. For now
+ // we just use <pre> to get fixed-width text formatting.
+
+ // If the comment itself contains block comment start or end markers,
+ // HTML-escape them so that they don't accidentally close the doc comment.
+ comments = EscapeJavadoc(comments);
+
+ std::vector<std::string> lines = Split(comments, "\n");
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+
+ printer->Print(" * <pre>\n");
+ for (int i = 0; i < lines.size(); i++) {
+ // Most lines should start with a space. Watch out for lines that start
+ // with a /, since putting that right after the leading asterisk will
+ // close the comment.
+ if (!lines[i].empty() && lines[i][0] == '/') {
+ printer->Print(" * $line$\n", "line", lines[i]);
+ } else {
+ printer->Print(" *$line$\n", "line", lines[i]);
+ }
+ }
+ printer->Print(
+ " * </pre>\n"
+ " *\n");
+ }
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(io::Printer* printer,
+ const DescriptorType* descriptor) {
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ WriteDocCommentBodyForLocation(printer, location);
+ }
+}
+
+static std::string FirstLineOf(const std::string& value) {
+ std::string result = value;
+
+ std::string::size_type pos = result.find_first_of('\n');
+ if (pos != std::string::npos) {
+ result.erase(pos);
+ }
+
+ // If line ends in an opening brace, make it "{ ... }" so it looks nice.
+ if (!result.empty() && result[result.size() - 1] == '{') {
+ result.append(" ... }");
+ }
+
+ return result;
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, message);
+ printer->Print(
+ " * Protobuf type {@code $fullname$}\n"
+ " */\n",
+ "fullname", EscapeJavadoc(message->full_name()));
+}
+
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
+ // We start the comment with the main body based on the comments from the
+ // .proto file (if present). We then continue with the field declaration,
+ // e.g.:
+ // optional string foo = 5;
+ // And then we end with the javadoc tags if applicable.
+ // If the field is a group, the debug string might end with {.
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, field);
+ printer->Print(" * <code>$def$</code>\n", "def",
+ EscapeJavadoc(FirstLineOf(field->DebugString())));
+ printer->Print(" */\n");
+}
+
+void WriteDeprecatedJavadoc(io::Printer* printer, const FieldDescriptor* field,
+ const FieldAccessorType type) {
+ if (!field->options().deprecated()) {
+ return;
+ }
+
+ // Lite codegen does not annotate set & clear methods with @Deprecated.
+ if (field->file()->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+ (type == SETTER || type == CLEARER)) {
+ return;
+ }
+
+ printer->Print(" * @deprecated\n");
+}
+
+void WriteFieldAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, field);
+ printer->Print(" * <code>$def$</code>\n", "def",
+ EscapeJavadoc(FirstLineOf(field->DebugString())));
+ WriteDeprecatedJavadoc(printer, field, type);
+ switch (type) {
+ case HAZZER:
+ printer->Print(" * @return Whether the $name$ field is set.\n", "name",
+ field->camelcase_name());
+ break;
+ case GETTER:
+ printer->Print(" * @return The $name$.\n", "name",
+ field->camelcase_name());
+ break;
+ case SETTER:
+ printer->Print(" * @param value The $name$ to set.\n", "name",
+ field->camelcase_name());
+ break;
+ case CLEARER:
+ // Print nothing
+ break;
+ // Repeated
+ case LIST_COUNT:
+ printer->Print(" * @return The count of $name$.\n", "name",
+ field->camelcase_name());
+ break;
+ case LIST_GETTER:
+ printer->Print(" * @return A list containing the $name$.\n", "name",
+ field->camelcase_name());
+ break;
+ case LIST_INDEXED_GETTER:
+ printer->Print(" * @param index The index of the element to return.\n");
+ printer->Print(" * @return The $name$ at the given index.\n", "name",
+ field->camelcase_name());
+ break;
+ case LIST_INDEXED_SETTER:
+ printer->Print(" * @param index The index to set the value at.\n");
+ printer->Print(" * @param value The $name$ to set.\n", "name",
+ field->camelcase_name());
+ break;
+ case LIST_ADDER:
+ printer->Print(" * @param value The $name$ to add.\n", "name",
+ field->camelcase_name());
+ break;
+ case LIST_MULTI_ADDER:
+ printer->Print(" * @param values The $name$ to add.\n", "name",
+ field->camelcase_name());
+ break;
+ }
+ if (builder) {
+ printer->Print(" * @return This builder for chaining.\n");
+ }
+ printer->Print(" */\n");
+}
+
+void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, field);
+ printer->Print(" * <code>$def$</code>\n", "def",
+ EscapeJavadoc(FirstLineOf(field->DebugString())));
+ WriteDeprecatedJavadoc(printer, field, type);
+ switch (type) {
+ case HAZZER:
+ // Should never happen
+ break;
+ case GETTER:
+ printer->Print(
+ " * @return The enum numeric value on the wire for $name$.\n", "name",
+ field->camelcase_name());
+ break;
+ case SETTER:
+ printer->Print(
+ " * @param value The enum numeric value on the wire for $name$ to "
+ "set.\n",
+ "name", field->camelcase_name());
+ break;
+ case CLEARER:
+ // Print nothing
+ break;
+ // Repeated
+ case LIST_COUNT:
+ // Should never happen
+ break;
+ case LIST_GETTER:
+ printer->Print(
+ " * @return A list containing the enum numeric values on the wire "
+ "for $name$.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_INDEXED_GETTER:
+ printer->Print(" * @param index The index of the value to return.\n");
+ printer->Print(
+ " * @return The enum numeric value on the wire of $name$ at the "
+ "given index.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_INDEXED_SETTER:
+ printer->Print(" * @param index The index to set the value at.\n");
+ printer->Print(
+ " * @param value The enum numeric value on the wire for $name$ to "
+ "set.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_ADDER:
+ printer->Print(
+ " * @param value The enum numeric value on the wire for $name$ to "
+ "add.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_MULTI_ADDER:
+ printer->Print(
+ " * @param values The enum numeric values on the wire for $name$ to "
+ "add.\n",
+ "name", field->camelcase_name());
+ break;
+ }
+ if (builder) {
+ printer->Print(" * @return This builder for chaining.\n");
+ }
+ printer->Print(" */\n");
+}
+
+void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, field);
+ printer->Print(" * <code>$def$</code>\n", "def",
+ EscapeJavadoc(FirstLineOf(field->DebugString())));
+ WriteDeprecatedJavadoc(printer, field, type);
+ switch (type) {
+ case HAZZER:
+ // Should never happen
+ break;
+ case GETTER:
+ printer->Print(" * @return The bytes for $name$.\n", "name",
+ field->camelcase_name());
+ break;
+ case SETTER:
+ printer->Print(" * @param value The bytes for $name$ to set.\n", "name",
+ field->camelcase_name());
+ break;
+ case CLEARER:
+ // Print nothing
+ break;
+ // Repeated
+ case LIST_COUNT:
+ // Should never happen
+ break;
+ case LIST_GETTER:
+ printer->Print(" * @return A list containing the bytes for $name$.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_INDEXED_GETTER:
+ printer->Print(" * @param index The index of the value to return.\n");
+ printer->Print(" * @return The bytes of the $name$ at the given index.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_INDEXED_SETTER:
+ printer->Print(" * @param index The index to set the value at.\n");
+ printer->Print(" * @param value The bytes of the $name$ to set.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_ADDER:
+ printer->Print(" * @param value The bytes of the $name$ to add.\n",
+ "name", field->camelcase_name());
+ break;
+ case LIST_MULTI_ADDER:
+ printer->Print(" * @param values The bytes of the $name$ to add.\n",
+ "name", field->camelcase_name());
+ break;
+ }
+ if (builder) {
+ printer->Print(" * @return This builder for chaining.\n");
+ }
+ printer->Print(" */\n");
+}
+
+// Enum
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, enum_);
+ printer->Print(
+ " * Protobuf enum {@code $fullname$}\n"
+ " */\n",
+ "fullname", EscapeJavadoc(enum_->full_name()));
+}
+
+void WriteEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, value);
+ printer->Print(
+ " * <code>$def$</code>\n"
+ " */\n",
+ "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+}
+
+void WriteServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, service);
+ printer->Print(
+ " * Protobuf service {@code $fullname$}\n"
+ " */\n",
+ "fullname", EscapeJavadoc(service->full_name()));
+}
+
+void WriteMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, method);
+ printer->Print(
+ " * <code>$def$</code>\n"
+ " */\n",
+ "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.h
new file mode 100644
index 00000000..2706effb
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment.h
@@ -0,0 +1,101 @@
+// 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_JAVA_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+
+#include <descriptor.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+enum FieldAccessorType {
+ HAZZER,
+ GETTER,
+ SETTER,
+ CLEARER,
+ // Repeated
+ LIST_COUNT,
+ LIST_GETTER,
+ LIST_INDEXED_GETTER,
+ LIST_INDEXED_SETTER,
+ LIST_ADDER,
+ LIST_MULTI_ADDER
+};
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
+void WriteFieldAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder = false);
+void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder = false);
+void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
+ const FieldDescriptor* field,
+ const FieldAccessorType type,
+ const bool builder = false);
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+void WriteEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value);
+void WriteServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service);
+void WriteMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method);
+
+// Exposed for testing only.
+PROTOC_EXPORT std::string EscapeJavadoc(const std::string& input);
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment_unittest.cc
new file mode 100644
index 00000000..cbeadd0e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -0,0 +1,67 @@
+// 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)
+
+#include <compiler/java/java_doc_comment.h>
+
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+TEST(JavaDocCommentTest, Escaping) {
+ EXPECT_EQ("foo /&#42; bar *&#47; baz", EscapeJavadoc("foo /* bar */ baz"));
+ EXPECT_EQ("foo /&#42;&#47; baz", EscapeJavadoc("foo /*/ baz"));
+ EXPECT_EQ("{&#64;foo}", EscapeJavadoc("{@foo}"));
+ EXPECT_EQ("&lt;i&gt;&amp;&lt;/i&gt;", EscapeJavadoc("<i>&</i>"));
+ EXPECT_EQ("foo&#92;u1234bar", EscapeJavadoc("foo\\u1234bar"));
+ EXPECT_EQ("&#64;deprecated", EscapeJavadoc("@deprecated"));
+}
+
+// TODO(kenton): It's hard to write a robust test of the doc comments -- we
+// can only really compare the output against a golden value, which is a
+// fairly tedious and fragile testing strategy. If we want to go that route,
+// it probably makes sense to bite the bullet and write a test that compares
+// the whole generated output for unittest.proto against a golden value, with
+// a very simple script that can be run to regenerate it with the latest code.
+// This would mean that updates to the golden file would have to be included
+// in any change to the code generator, which would actually be fairly useful
+// as it allows the reviewer to see clearly how the generated code is
+// changing.
+
+} // namespace
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.cc
new file mode 100644
index 00000000..f3eb4bc2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.cc
@@ -0,0 +1,391 @@
+// 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 <map>
+#include <string>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api, Context* context)
+ : descriptor_(descriptor),
+ immutable_api_(immutable_api),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ canonical_values_.push_back(value);
+ } else {
+ Alias alias;
+ alias.value = value;
+ alias.canonical_value = canonical_value;
+ aliases_.push_back(alias);
+ }
+ }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
+ printer->Print(
+ "$deprecation$public enum $classname$\n"
+ " implements com.google.protobuf.ProtocolMessageEnum {\n",
+ "classname", descriptor_->name(), "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "");
+ printer->Annotate("classname", descriptor_);
+ printer->Indent();
+
+ bool ordinal_is_index = true;
+ std::string index_text = "ordinal()";
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ if (canonical_values_[i]->index() != i) {
+ ordinal_is_index = false;
+ index_text = "index";
+ break;
+ }
+ }
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["name"] = canonical_values_[i]->name();
+ vars["index"] = StrCat(canonical_values_[i]->index());
+ vars["number"] = StrCat(canonical_values_[i]->number());
+ WriteEnumValueDocComment(printer, canonical_values_[i]);
+ if (canonical_values_[i]->options().deprecated()) {
+ printer->Print("@java.lang.Deprecated\n");
+ }
+ if (ordinal_is_index) {
+ printer->Print(vars, "$name$($number$),\n");
+ } else {
+ printer->Print(vars, "$name$($index$, $number$),\n");
+ }
+ printer->Annotate("name", canonical_values_[i]);
+ }
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ if (ordinal_is_index) {
+ printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
+ } else {
+ printer->Print("${$UNRECOGNIZED$}$(-1, -1),\n", "{", "", "}", "");
+ }
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ printer->Print(
+ ";\n"
+ "\n");
+
+ // -----------------------------------------------------------------
+
+ for (int i = 0; i < aliases_.size(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["classname"] = descriptor_->name();
+ vars["name"] = aliases_[i].value->name();
+ vars["canonical_name"] = aliases_[i].canonical_value->name();
+ WriteEnumValueDocComment(printer, aliases_[i].value);
+ printer->Print(
+ vars, "public static final $classname$ $name$ = $canonical_name$;\n");
+ printer->Annotate("name", aliases_[i].value);
+ }
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["name"] = descriptor_->value(i)->name();
+ vars["number"] = StrCat(descriptor_->value(i)->number());
+ vars["{"] = "";
+ vars["}"] = "";
+ vars["deprecation"] = descriptor_->value(i)->options().deprecated()
+ ? "@java.lang.Deprecated "
+ : "";
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ printer->Print(vars,
+ "$deprecation$public static final int ${$$name$_VALUE$}$ = "
+ "$number$;\n");
+ printer->Annotate("{", "}", descriptor_->value(i));
+ }
+ printer->Print("\n");
+
+ // -----------------------------------------------------------------
+
+ printer->Print(
+ "\n"
+ "public final int getNumber() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ if (ordinal_is_index) {
+ printer->Print(
+ " if (this == UNRECOGNIZED) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ } else {
+ printer->Print(
+ " if (index == -1) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ }
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
+ "\n"
+ "/**\n"
+ " * @param value The numeric wire value of the corresponding enum "
+ "entry.\n"
+ " * @return The enum associated with the given numeric wire value.\n"
+ " * @deprecated Use {@link #forNumber(int)} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public static $classname$ valueOf(int value) {\n"
+ " return forNumber(value);\n"
+ "}\n"
+ "\n"
+ "/**\n"
+ " * @param value The numeric wire value of the corresponding enum "
+ "entry.\n"
+ " * @return The enum associated with the given numeric wire value.\n"
+ " */\n"
+ "public static $classname$ forNumber(int value) {\n"
+ " switch (value) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ printer->Print("case $number$: return $name$;\n", "name",
+ canonical_values_[i]->name(), "number",
+ StrCat(canonical_values_[i]->number()));
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+ " internalGetValueMap() {\n"
+ " return internalValueMap;\n"
+ "}\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
+ " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+ " public $classname$ findValueByNumber(int number) {\n"
+ " return $classname$.forNumber(number);\n"
+ " }\n"
+ " };\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ // -----------------------------------------------------------------
+ // Reflection
+
+ if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
+ printer->Print(
+ "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
+ " getValueDescriptor() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ if (ordinal_is_index) {
+ printer->Print(
+ " if (this == UNRECOGNIZED) {\n"
+ " throw new java.lang.IllegalStateException(\n"
+ " \"Can't get the descriptor of an unrecognized enum "
+ "value.\");\n"
+ " }\n");
+ } else {
+ printer->Print(
+ " if (index == -1) {\n"
+ " throw new java.lang.IllegalStateException(\n"
+ " \"Can't get the descriptor of an unrecognized enum "
+ "value.\");\n"
+ " }\n");
+ }
+ }
+ printer->Print(
+ " return getDescriptor().getValues().get($index_text$);\n"
+ "}\n"
+ "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
+ " getDescriptorForType() {\n"
+ " return getDescriptor();\n"
+ "}\n"
+ "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
+ " getDescriptor() {\n",
+ "index_text", index_text);
+
+ // TODO(kenton): Cache statically? Note that we can't access descriptors
+ // at module init time because it wouldn't work with descriptor.proto, but
+ // we can cache the value the first time getDescriptor() is called.
+ if (descriptor_->containing_type() == NULL) {
+ // The class generated for the File fully populates the descriptor with
+ // extensions in both the mutable and immutable cases. (In the mutable api
+ // this is accomplished by attempting to load the immutable outer class).
+ printer->Print(
+ " return $file$.getDescriptor().getEnumTypes().get($index$);\n",
+ "file",
+ name_resolver_->GetClassName(descriptor_->file(), immutable_api_),
+ "index", StrCat(descriptor_->index()));
+ } else {
+ printer->Print(
+ " return $parent$.$descriptor$.getEnumTypes().get($index$);\n",
+ "parent",
+ name_resolver_->GetClassName(descriptor_->containing_type(),
+ immutable_api_),
+ "descriptor",
+ descriptor_->containing_type()
+ ->options()
+ .no_standard_descriptor_accessor()
+ ? "getDefaultInstance().getDescriptorForType()"
+ : "getDescriptor()",
+ "index", StrCat(descriptor_->index()));
+ }
+
+ printer->Print(
+ "}\n"
+ "\n"
+ "private static final $classname$[] VALUES = ",
+ "classname", descriptor_->name());
+
+ if (CanUseEnumValues()) {
+ // If the constants we are going to output are exactly the ones we
+ // have declared in the Java enum in the same order, then we can use
+ // the values() method that the Java compiler automatically generates
+ // for every enum.
+ printer->Print("values();\n");
+ } else {
+ printer->Print("getStaticValuesArray();\n");
+ printer->Print("private static $classname$[] getStaticValuesArray() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Print(
+ "return new $classname$[] {\n"
+ " ",
+ "classname", descriptor_->name());
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ printer->Print("$name$, ", "name", descriptor_->value(i)->name());
+ }
+ printer->Print(
+ "\n"
+ "};\n");
+ printer->Outdent();
+ printer->Print("}");
+ }
+
+ printer->Print(
+ "\n"
+ "public static $classname$ valueOf(\n"
+ " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
+ " if (desc.getType() != getDescriptor()) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"EnumValueDescriptor is not for this type.\");\n"
+ " }\n",
+ "classname", descriptor_->name());
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (desc.getIndex() == -1) {\n"
+ " return UNRECOGNIZED;\n"
+ " }\n");
+ }
+ printer->Print(
+ " return VALUES[desc.getIndex()];\n"
+ "}\n"
+ "\n");
+
+ if (!ordinal_is_index) {
+ printer->Print("private final int index;\n");
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ printer->Print("private final int value;\n\n");
+
+ if (ordinal_is_index) {
+ printer->Print("private $classname$(int value) {\n", "classname",
+ descriptor_->name());
+ } else {
+ printer->Print("private $classname$(int index, int value) {\n", "classname",
+ descriptor_->name());
+ }
+ if (HasDescriptorMethods(descriptor_, context_->EnforceLite()) &&
+ !ordinal_is_index) {
+ printer->Print(" this.index = index;\n");
+ }
+ printer->Print(
+ " this.value = value;\n"
+ "}\n");
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+bool EnumGenerator::CanUseEnumValues() {
+ if (canonical_values_.size() != descriptor_->value_count()) {
+ return false;
+ }
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.h
new file mode 100644
index 00000000..cae2ffea
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum.h
@@ -0,0 +1,100 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+
+#include <string>
+#include <vector>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumGenerator {
+ public:
+ EnumGenerator(const EnumDescriptor* descriptor, bool immutable_api,
+ Context* context);
+ ~EnumGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+
+ // The proto language allows multiple enum constants to have the same
+ // numeric value. Java, however, does not allow multiple enum constants to
+ // be considered equivalent. We treat the first defined constant for any
+ // given numeric value as "canonical" and the rest as aliases of that
+ // canonical value.
+ std::vector<const EnumValueDescriptor*> canonical_values_;
+
+ struct Alias {
+ const EnumValueDescriptor* value;
+ const EnumValueDescriptor* canonical_value;
+ };
+ std::vector<Alias> aliases_;
+
+ bool immutable_api_;
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ bool CanUseEnumValues();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.cc
new file mode 100644
index 00000000..51e944df
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.cc
@@ -0,0 +1,1176 @@
+// 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 <compiler/java/java_enum_field.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->enum_type());
+ (*variables)["kt_type"] = (*variables)["type"];
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->enum_type());
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_number"] =
+ StrCat(descriptor->default_value_enum()->number());
+ (*variables)["tag"] = StrCat(
+ static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ 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)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["on_changed"] = "onChanged();";
+ // Use deprecated valueOf() method to be compatible with old generated code
+ // for v2.5.0/v2.6.1.
+ // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
+ // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
+ (*variables)["for_number"] = "valueOf";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["set_has_field_bit_builder"] =
+ GenerateSetBit(builderBitIndex) + ";";
+ (*variables)["clear_has_field_bit_builder"] =
+ GenerateClearBit(builderBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_builder"] = "";
+ (*variables)["clear_has_field_bit_builder"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"] +
+ ".getNumber()";
+ }
+
+ // For repeated 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);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+ } else {
+ (*variables)["unknown"] = (*variables)["default"];
+ }
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor), name_resolver_,
+ &variables_);
+}
+
+ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
+
+int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
+ return GetNumBitsForMessage();
+}
+
+void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_, "private int $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override $deprecation$public boolean "
+ "${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override $deprecation$public int "
+ "${$get$capitalized_name$Value$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override $deprecation$public $type$ "
+ "${$get$capitalized_name$$}$() {\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ " $type$ result = $type$.$for_number$($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private int $name$_ = $default_number$;\n");
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override $deprecation$public boolean "
+ "${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_builder$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override $deprecation$public int "
+ "${$get$capitalized_name$Value$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$Value$}$(int value) {\n"
+ " $set_has_field_bit_builder$\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ " $type$ result = $type$.$for_number$($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ 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.getNumber();\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " $clear_has_field_bit_builder$\n"
+ " $name$_ = $default_number$;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $default_number$;\n"
+ "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ } else if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "if (other.$name$_ != $default_number$) {\n"
+ " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
+ "}\n");
+ } else {
+ GOOGLE_LOG(FATAL) << "Can't reach here.";
+ }
+}
+
+void ImmutableEnumFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_from_local$) {\n"
+ " $set_has_field_bit_to_local$;\n"
+ "}\n");
+ }
+ printer->Print(variables_, "result.$name$_ = $name$_;\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ "$type$ value = $type$.$for_number$(rawValue);\n"
+ "if (value == null) {\n"
+ " unknownFields.mergeVarintField($number$, rawValue);\n"
+ "} else {\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = rawValue;\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.writeEnum($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n");
+}
+
+void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + $name$_;\n");
+}
+
+std::string ImmutableEnumFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
+ context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
+
+void ImmutableEnumOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return (java.lang.Integer) $oneof_name$_;\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ " $type$ result = $type$.$for_number$(\n"
+ " (java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$Value$}$(int value) {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ " $type$ result = $type$.$for_number$(\n"
+ " (java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value.getNumber();\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " $on_changed$\n"
+ " }\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " result.$oneof_name$_ = $oneof_name$_;\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
+ } else {
+ printer->Print(variables_,
+ "set$capitalized_name$(other.get$capitalized_name$());\n");
+ }
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "@SuppressWarnings(\"deprecation\")\n"
+ "$type$ value = $type$.$for_number$(rawValue);\n"
+ "if (value == null) {\n"
+ " unknownFields.mergeVarintField($number$, rawValue);\n"
+ "} else {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = rawValue;\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "if (get$capitalized_name$Value()\n"
+ " != other.get$capitalized_name$Value()) return false;\n");
+ } else {
+ printer->Print(
+ variables_,
+ "if (!get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$())) return false;\n");
+ }
+}
+
+void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(
+ variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+ }
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor), name_resolver_,
+ &variables_);
+}
+
+RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
+
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList();\n");
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value(int index);\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private java.util.List<java.lang.Integer> $name$_;\n"
+ "private static final "
+ "com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$> $name$_converter_ =\n"
+ " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$>() {\n"
+ " public $type$ convert(java.lang.Integer from) {\n"
+ " @SuppressWarnings(\"deprecation\")\n"
+ " $type$ result = $type$.$for_number$(from);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " };\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "${$get$capitalized_name$ValueList$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int "
+ "${$get$capitalized_name$Value$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldGenerator::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 reference 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<java.lang.Integer> $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<java.lang.Integer>($name$_);\n"
+ " $set_mutable_bit_builder$;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ 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 new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ true);
+ 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.getNumber());\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ 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.getNumber());\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.add(value.getNumber());\n"
+ " }\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ 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");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "${$get$capitalized_name$ValueList$}$() {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public int "
+ "${$get$capitalized_name$Value$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$Value$}$(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_MULTI_ADDER, /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (int value : values) {\n"
+ " $name$_.add(value);\n"
+ " }\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void RepeatedImmutableEnumFieldGenerator::
+ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = java.util.Collections.emptyList();\n"
+ "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::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 RepeatedImmutableEnumFieldGenerator::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 RepeatedImmutableEnumFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ // Read and store the enum
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
+ "$name$_.add(rawValue);\n");
+ } else {
+ printer->Print(
+ variables_,
+ "int rawValue = input.readEnum();\n"
+ "@SuppressWarnings(\"deprecation\")\n"
+ "$type$ value = $type$.$for_number$(rawValue);\n"
+ "if (value == null) {\n"
+ " unknownFields.mergeVarintField($number$, rawValue);\n"
+ "} else {\n"
+ " if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ " }\n"
+ " $name$_.add(rawValue);\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldGenerator::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 RepeatedImmutableEnumFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeUInt32NoTag($tag$);\n"
+ " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeEnumNoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeEnum($number$, $name$_.get(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldGenerator::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));\n"
+ "}\n");
+ printer->Print("size += dataSize;\n");
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeUInt32SizeNoTag(dataSize);\n"
+ "}");
+ } else {
+ printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$name$_.equals(other.$name$_)) return false;\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
+ "}\n");
+}
+
+void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.h
new file mode 100644
index 00000000..1e88bbf3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field.h
@@ -0,0 +1,161 @@
+// 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_JAVA_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ Context* context);
+ ~ImmutableEnumFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator
+ // ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator);
+};
+
+class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
+ public:
+ ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ Context* context);
+ ~ImmutableEnumOneofFieldGenerator();
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
+};
+
+class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit RepeatedImmutableEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableEnumFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.cc
new file mode 100644
index 00000000..ffc28ef0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.cc
@@ -0,0 +1,918 @@
+// 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 <compiler/java/java_enum_field_lite.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool EnableExperimentalRuntimeForLite() {
+#ifdef PROTOBUF_EXPERIMENT
+ return PROTOBUF_EXPERIMENT;
+#else // PROTOBUF_EXPERIMENT
+ return false;
+#endif // !PROTOBUF_EXPERIMENT
+}
+
+void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->enum_type());
+ (*variables)["kt_type"] = (*variables)["type"];
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->enum_type());
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_number"] =
+ StrCat(descriptor->default_value_enum()->number());
+ (*variables)["tag"] = StrCat(
+ static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ 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)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["required"] = descriptor->is_required() ? "true" : "false";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"] +
+ ".getNumber()";
+ }
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+ } else {
+ (*variables)["unknown"] = (*variables)["default"];
+ }
+
+ // We use `x.getClass()` as a null check because it generates less bytecode
+ // than an `if (x == null) { throw ... }` statement.
+ (*variables)["null_check"] = "value.getClass();\n";
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : descriptor_(descriptor),
+ messageBitIndex_(messageBitIndex),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor), name_resolver_,
+ &variables_);
+}
+
+ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private int $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " $type$ result = $type$.forNumber($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_has_field_bit_message$"
+ " $name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " $name$_ = value.getNumber();\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ " $name$_ = $default_number$;\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$Value$}$(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ if (!IsDefaultValueJavaDefault(descriptor_)) {
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ if (HasHasbit(descriptor_)) {
+ WriteIntToUtf16CharSequence(messageBitIndex_, output);
+ }
+ printer->Print(variables_, "\"$name$_\",\n");
+ if (!SupportUnknownEnumValue((descriptor_))) {
+ PrintEnumVerifierLogic(printer, descriptor_, variables_,
+ /*var_name=*/"$type$",
+ /*terminating_string=*/",\n",
+ /*enforce_lite=*/context_->EnforceLite());
+ }
+}
+
+std::string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldLiteGenerator::ImmutableEnumOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : ImmutableEnumFieldLiteGenerator(descriptor, messageBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {}
+
+void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return (java.lang.Integer) $oneof_name$_;\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $type$ result = $type$.forNumber((java.lang.Integer) "
+ "$oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " $oneof_name$_ = value.getNumber();\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
+ if (!SupportUnknownEnumValue(descriptor_)) {
+ PrintEnumVerifierLogic(printer, descriptor_, variables_,
+ /*var_name=*/"$type$",
+ /*terminating_string=*/",\n",
+ /*enforce_lite=*/context_->EnforceLite());
+ }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$Value$}$(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldLiteGenerator::
+ RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context)
+ : descriptor_(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor), name_resolver_,
+ &variables_);
+}
+
+RepeatedImmutableEnumFieldLiteGenerator::
+ ~RepeatedImmutableEnumFieldLiteGenerator() {}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList();\n");
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value(int index);\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.Internal.IntList $name$_;\n"
+ "private static final "
+ "com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$> $name$_converter_ =\n"
+ " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$>() {\n"
+ " @java.lang.Override\n"
+ " public $type$ convert(java.lang.Integer from) {\n"
+ " $type$ result = $type$.forNumber(from);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " };\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ // NB: Do not use the "$name$_converter_" field; the usage of generics
+ // (and requisite upcasts to Object) prevent optimizations. Even
+ // without any optimizations, the below code is cheaper because it
+ // avoids boxing an int and a checkcast from the generics.
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " $type$ result = $type$.forNumber($name$_.getInt(index));\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "${$get$capitalized_name$ValueList$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int "
+ "${$get$capitalized_name$Value$}$(int index) {\n"
+ " return $name$_.getInt(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() &&
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
+ }
+
+ // Generate private setters for the builder to proxy into.
+ printer->Print(
+ variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ // Use a temporary to avoid a redundant iget-object.
+ " com.google.protobuf.Internal.IntList tmp = $name$_;\n"
+ " if (!tmp.isModifiable()) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
+ " }\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " $null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.setInt(index, value.getNumber());\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addInt(value.getNumber());\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.addInt(value.getNumber());\n"
+ " }\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyIntList();\n"
+ "}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.setInt(index, value);\n"
+ "}\n");
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Value(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addInt(value);\n"
+ "}\n");
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_MULTI_ADDER);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$Value(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (int value : values) {\n"
+ " $name$_.addInt(value);\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ printer->Print(variables_, "\"$name$_\",\n");
+ if (!SupportUnknownEnumValue(descriptor_->file())) {
+ PrintEnumVerifierLogic(printer, descriptor_, variables_,
+ /*var_name=*/"$type$",
+ /*terminating_string=*/",\n",
+ /*enforce_lite=*/context_->EnforceLite());
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return instance.get$capitalized_name$List();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "${$get$capitalized_name$ValueList$}$() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$ValueList());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int "
+ "${$get$capitalized_name$Value$}$(int index) {\n"
+ " return instance.get$capitalized_name$Value(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_SETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
+ " int index, int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$Value$}$(int value) {\n"
+ " instance.add$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
+ LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$Value(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyIntList();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.h
new file mode 100644
index 00000000..8073f393
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_field_lite.h
@@ -0,0 +1,140 @@
+// 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_JAVA_ENUM_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutableEnumFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator
+ // ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ const int messageBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
+};
+
+class ImmutableEnumOneofFieldLiteGenerator
+ : public ImmutableEnumFieldLiteGenerator {
+ public:
+ ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, Context* context);
+ ~ImmutableEnumOneofFieldLiteGenerator() override;
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableEnumFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+ ~RepeatedImmutableEnumFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.cc
new file mode 100644
index 00000000..7cfad624
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.cc
@@ -0,0 +1,235 @@
+// 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 <map>
+#include <string>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum_lite.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+#include <stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api, Context* context)
+ : descriptor_(descriptor),
+ immutable_api_(immutable_api),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ canonical_values_.push_back(value);
+ } else {
+ Alias alias;
+ alias.value = value;
+ alias.canonical_value = canonical_value;
+ aliases_.push_back(alias);
+ }
+ }
+}
+
+EnumLiteGenerator::~EnumLiteGenerator() {}
+
+void EnumLiteGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
+ printer->Print(
+ "$deprecation$public enum $classname$\n"
+ " implements com.google.protobuf.Internal.EnumLite {\n",
+ "classname", descriptor_->name(), "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "");
+ printer->Annotate("classname", descriptor_);
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["name"] = canonical_values_[i]->name();
+ vars["number"] = StrCat(canonical_values_[i]->number());
+ WriteEnumValueDocComment(printer, canonical_values_[i]);
+ if (canonical_values_[i]->options().deprecated()) {
+ printer->Print("@java.lang.Deprecated\n");
+ }
+ printer->Print(vars, "$name$($number$),\n");
+ printer->Annotate("name", canonical_values_[i]);
+ }
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ printer->Print(
+ ";\n"
+ "\n");
+
+ // -----------------------------------------------------------------
+
+ for (int i = 0; i < aliases_.size(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["classname"] = descriptor_->name();
+ vars["name"] = aliases_[i].value->name();
+ vars["canonical_name"] = aliases_[i].canonical_value->name();
+ WriteEnumValueDocComment(printer, aliases_[i].value);
+ printer->Print(
+ vars, "public static final $classname$ $name$ = $canonical_name$;\n");
+ printer->Annotate("name", aliases_[i].value);
+ }
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ std::map<std::string, std::string> vars;
+ vars["name"] = descriptor_->value(i)->name();
+ vars["number"] = StrCat(descriptor_->value(i)->number());
+ vars["{"] = "";
+ vars["}"] = "";
+ vars["deprecation"] = descriptor_->value(i)->options().deprecated()
+ ? "@java.lang.Deprecated "
+ : "";
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ printer->Print(vars,
+ "$deprecation$public static final int ${$$name$_VALUE$}$ = "
+ "$number$;\n");
+ printer->Annotate("{", "}", descriptor_->value(i));
+ }
+ printer->Print("\n");
+
+ // -----------------------------------------------------------------
+
+ printer->Print(
+ "\n"
+ "@java.lang.Override\n"
+ "public final int getNumber() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (this == UNRECOGNIZED) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
+ "\n"
+ "/**\n"
+ " * @param value The number of the enum to look for.\n"
+ " * @return The enum associated with the given number.\n"
+ " * @deprecated Use {@link #forNumber(int)} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public static $classname$ valueOf(int value) {\n"
+ " return forNumber(value);\n"
+ "}\n"
+ "\n"
+ "public static $classname$ forNumber(int value) {\n"
+ " switch (value) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ printer->Print("case $number$: return $name$;\n", "name",
+ canonical_values_[i]->name(), "number",
+ StrCat(canonical_values_[i]->number()));
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+ " internalGetValueMap() {\n"
+ " return internalValueMap;\n"
+ "}\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
+ " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+ " @java.lang.Override\n"
+ " public $classname$ findValueByNumber(int number) {\n"
+ " return $classname$.forNumber(number);\n"
+ " }\n"
+ " };\n"
+ "\n"
+ "public static com.google.protobuf.Internal.EnumVerifier \n"
+ " internalGetVerifier() {\n"
+ " return $classname$Verifier.INSTANCE;\n"
+ "}\n"
+ "\n"
+ "private static final class $classname$Verifier implements \n"
+ " com.google.protobuf.Internal.EnumVerifier { \n"
+ " static final com.google.protobuf.Internal.EnumVerifier "
+ " INSTANCE = new $classname$Verifier();\n"
+ " @java.lang.Override\n"
+ " public boolean isInRange(int number) {\n"
+ " return $classname$.forNumber(number) != null;\n"
+ " }\n"
+ " };\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "private final int value;\n\n"
+ "private $classname$(int value) {\n",
+ "classname", descriptor_->name());
+ printer->Print(
+ " this.value = value;\n"
+ "}\n");
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.h
new file mode 100644
index 00000000..0b706d8e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_enum_lite.h
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+
+#include <string>
+#include <vector>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumLiteGenerator {
+ public:
+ EnumLiteGenerator(const EnumDescriptor* descriptor, bool immutable_api,
+ Context* context);
+ ~EnumLiteGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+
+ // The proto language allows multiple enum constants to have the same
+ // numeric value. Java, however, does not allow multiple enum constants to
+ // be considered equivalent. We treat the first defined constant for any
+ // given numeric value as "canonical" and the rest as aliases of that
+ // canonical value.
+ std::vector<const EnumValueDescriptor*> canonical_values_;
+
+ struct Alias {
+ const EnumValueDescriptor* value;
+ const EnumValueDescriptor* canonical_value;
+ };
+ std::vector<Alias> aliases_;
+
+ bool immutable_api_;
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.cc
new file mode 100644
index 00000000..d45fd9c1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.cc
@@ -0,0 +1,172 @@
+// 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 <compiler/java/java_extension.h>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionGenerator::ImmutableExtensionGenerator(
+ const FieldDescriptor* descriptor, Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ if (descriptor_->extension_scope() != NULL) {
+ scope_ =
+ name_resolver_->GetImmutableClassName(descriptor_->extension_scope());
+ } else {
+ scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+ }
+}
+
+ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {}
+
+// Initializes the vars referenced in the generated code templates.
+void ExtensionGenerator::InitTemplateVars(
+ const FieldDescriptor* descriptor, const std::string& scope, bool immutable,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* vars_pointer) {
+ std::map<std::string, std::string>& vars = *vars_pointer;
+ vars["scope"] = scope;
+ vars["name"] = UnderscoresToCamelCaseCheckReserved(descriptor);
+ vars["containing_type"] =
+ name_resolver->GetClassName(descriptor->containing_type(), immutable);
+ vars["number"] = StrCat(descriptor->number());
+ vars["constant_name"] = FieldConstantName(descriptor);
+ vars["index"] = StrCat(descriptor->index());
+ vars["default"] = descriptor->is_repeated()
+ ? ""
+ : DefaultValue(descriptor, immutable, name_resolver);
+ vars["type_constant"] = FieldTypeName(GetType(descriptor));
+ vars["packed"] = descriptor->is_packed() ? "true" : "false";
+ vars["enum_map"] = "null";
+ vars["prototype"] = "null";
+
+ JavaType java_type = GetJavaType(descriptor);
+ std::string singular_type;
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ singular_type =
+ name_resolver->GetClassName(descriptor->message_type(), immutable);
+ vars["prototype"] = singular_type + ".getDefaultInstance()";
+ break;
+ case JAVATYPE_ENUM:
+ singular_type =
+ name_resolver->GetClassName(descriptor->enum_type(), immutable);
+ vars["enum_map"] = singular_type + ".internalGetValueMap()";
+ break;
+ case JAVATYPE_STRING:
+ singular_type = "java.lang.String";
+ break;
+ case JAVATYPE_BYTES:
+ singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]";
+ 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 ImmutableExtensionGenerator::Generate(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ const bool kUseImmutableNames = true;
+ InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+ &vars);
+ printer->Print(vars, "public static final int $constant_name$ = $number$;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ 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");
+ }
+ printer->Annotate("name", descriptor_);
+}
+
+int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
+ io::Printer* printer) {
+ int bytecode_estimate = 0;
+ if (descriptor_->extension_scope() == NULL) {
+ // Only applies to non-nested extensions.
+ printer->Print(
+ "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
+ "name", UnderscoresToCamelCaseCheckReserved(descriptor_), "index",
+ StrCat(descriptor_->index()));
+ bytecode_estimate += 21;
+ }
+ return bytecode_estimate;
+}
+
+int ImmutableExtensionGenerator::GenerateRegistrationCode(
+ io::Printer* printer) {
+ printer->Print("registry.add($scope$.$name$);\n", "scope", scope_, "name",
+ UnderscoresToCamelCaseCheckReserved(descriptor_));
+ return 7;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.h
new file mode 100644
index 00000000..823190d7
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension.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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
+
+#include <map>
+#include <string>
+
+#include <stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor; // descriptor.h
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for an extension, which may be within the scope of some
+// message or may be at file scope. This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ExtensionGenerator {
+ public:
+ explicit ExtensionGenerator() {}
+ virtual ~ExtensionGenerator() {}
+
+ virtual void Generate(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile
+ // to
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile
+ // to
+ virtual int GenerateRegistrationCode(io::Printer* printer) = 0;
+
+ protected:
+ static void InitTemplateVars(
+ const FieldDescriptor* descriptor, const std::string& scope,
+ bool immutable, ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* vars_pointer);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+class ImmutableExtensionGenerator : public ExtensionGenerator {
+ public:
+ explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor,
+ Context* context);
+ virtual ~ImmutableExtensionGenerator();
+
+ void Generate(io::Printer* printer) override;
+ int GenerateNonNestedInitializationCode(io::Printer* printer) override;
+ int GenerateRegistrationCode(io::Printer* printer) override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ ClassNameResolver* name_resolver_;
+ std::string scope_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.cc
new file mode 100644
index 00000000..cf1975a0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.cc
@@ -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 <compiler/java/java_extension_lite.h>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
+ const FieldDescriptor* descriptor, Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ if (descriptor_->extension_scope() != NULL) {
+ scope_ =
+ name_resolver_->GetImmutableClassName(descriptor_->extension_scope());
+ } else {
+ scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+ }
+}
+
+ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {}
+
+void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ const bool kUseImmutableNames = true;
+ InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+ &vars);
+ printer->Print(vars, "public static final int $constant_name$ = $number$;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ 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"
+ " $singular_type$.class);\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"
+ " $singular_type$.class);\n");
+ }
+ printer->Annotate("name", descriptor_);
+}
+
+int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode(
+ io::Printer* printer) {
+ return 0;
+}
+
+int ImmutableExtensionLiteGenerator::GenerateRegistrationCode(
+ io::Printer* printer) {
+ printer->Print("registry.add($scope$.$name$);\n", "scope", scope_, "name",
+ UnderscoresToCamelCaseCheckReserved(descriptor_));
+ return 7;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.h
new file mode 100644
index 00000000..0e38079f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_extension_lite.h
@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+
+#include <map>
+#include <string>
+
+#include <stubs/common.h>
+#include <compiler/java/java_extension.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for a lite extension, which may be within the scope of some
+// message or may be at file scope. This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ImmutableExtensionLiteGenerator : public ExtensionGenerator {
+ public:
+ explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor,
+ Context* context);
+ virtual ~ImmutableExtensionLiteGenerator();
+
+ void Generate(io::Printer* printer) override;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateNonNestedInitializationCode(io::Printer* printer) override;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateRegistrationCode(io::Printer* printer) override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ ClassNameResolver* name_resolver_;
+ std::string scope_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.cc
new file mode 100644
index 00000000..5da51b22
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.cc
@@ -0,0 +1,312 @@
+// 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 <compiler/java/java_field.h>
+
+#include <memory>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_enum_field.h>
+#include <compiler/java/java_enum_field_lite.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_map_field.h>
+#include <compiler/java/java_map_field_lite.h>
+#include <compiler/java/java_message_field.h>
+#include <compiler/java/java_message_field_lite.h>
+#include <compiler/java/java_primitive_field.h>
+#include <compiler/java/java_primitive_field_lite.h>
+#include <compiler/java/java_string_field.h>
+#include <compiler/java/java_string_field_lite.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+ImmutableFieldGenerator* MakeImmutableGenerator(const FieldDescriptor* field,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new RepeatedImmutableEnumFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new RepeatedImmutableStringFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new RepeatedImmutablePrimitiveFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ if (IsRealOneof(field)) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new ImmutableMessageOneofFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumOneofFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringOneofFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveOneofFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new ImmutableMessageFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveFieldGenerator(field, messageBitIndex,
+ builderBitIndex, context);
+ }
+ }
+ }
+}
+
+ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
+ const FieldDescriptor* field, int messageBitIndex, Context* context) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldLiteGenerator(field, messageBitIndex,
+ context);
+ } else {
+ return new RepeatedImmutableMessageFieldLiteGenerator(
+ field, messageBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new RepeatedImmutableEnumFieldLiteGenerator(
+ field, messageBitIndex, context);
+ case JAVATYPE_STRING:
+ return new RepeatedImmutableStringFieldLiteGenerator(
+ field, messageBitIndex, context);
+ default:
+ return new RepeatedImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, context);
+ }
+ } else {
+ if (IsRealOneof(field)) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new ImmutableMessageOneofFieldLiteGenerator(
+ field, messageBitIndex, context);
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumOneofFieldLiteGenerator(
+ field, messageBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringOneofFieldLiteGenerator(
+ field, messageBitIndex, context);
+ default:
+ return new ImmutablePrimitiveOneofFieldLiteGenerator(
+ field, messageBitIndex, context);
+ }
+ } else {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex,
+ context);
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex,
+ context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringFieldLiteGenerator(field, messageBitIndex,
+ context);
+ default:
+ return new ImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, context);
+ }
+ }
+ }
+}
+
+
+static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) {
+ // 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.";
+}
+
+} // namespace
+
+ImmutableFieldGenerator::~ImmutableFieldGenerator() {}
+
+void ImmutableFieldGenerator::GenerateParsingCodeFromPacked(
+ io::Printer* printer) const {
+ ReportUnexpectedPackedFieldsCall(printer);
+}
+
+ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {}
+
+// ===================================================================
+
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), field_generators_(descriptor->field_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++) {
+ ImmutableFieldGenerator* generator = MakeImmutableGenerator(
+ descriptor->field(i), messageBitIndex, builderBitIndex, context);
+ field_generators_[i].reset(generator);
+ messageBitIndex += generator->GetNumBitsForMessage();
+ builderBitIndex += generator->GetNumBitsForBuilder();
+ }
+}
+
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), field_generators_(descriptor->field_count()) {
+ // Construct all the FieldGenerators and assign them bit indices for their
+ // bit fields.
+ int messageBitIndex = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator(
+ descriptor->field(i), messageBitIndex, context);
+ field_generators_[i].reset(generator);
+ messageBitIndex += generator->GetNumBitsForMessage();
+ }
+}
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
+
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ const FieldGeneratorInfo* info,
+ std::map<std::string, std::string>* variables) {
+ (*variables)["field_name"] = descriptor->name();
+ (*variables)["name"] = info->name;
+ (*variables)["classname"] = descriptor->containing_type()->name();
+ (*variables)["capitalized_name"] = info->capitalized_name;
+ (*variables)["disambiguated_reason"] = info->disambiguated_reason;
+ (*variables)["constant_name"] = FieldConstantName(descriptor);
+ (*variables)["number"] = StrCat(descriptor->number());
+ (*variables)["kt_dsl_builder"] = "_builder";
+ // These variables are placeholders to pick out the beginning and ends of
+ // identifiers for annotations (when doing so with existing variables would
+ // be ambiguous or impossible). They should never be set to anything but the
+ // empty string.
+ (*variables)["{"] = "";
+ (*variables)["}"] = "";
+ (*variables)["kt_name"] =
+ IsForbiddenKotlin(info->name) ? info->name + "_" : info->name;
+ (*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name)
+ ? info->capitalized_name + "_"
+ : info->capitalized_name;
+ if (!descriptor->is_repeated()) {
+ (*variables)["annotation_field_type"] = FieldTypeName(descriptor->type());
+ } else if (GetJavaType(descriptor) == JAVATYPE_MESSAGE &&
+ IsMapEntry(descriptor->message_type())) {
+ (*variables)["annotation_field_type"] =
+ std::string(FieldTypeName(descriptor->type())) + "MAP";
+ } else {
+ (*variables)["annotation_field_type"] =
+ std::string(FieldTypeName(descriptor->type())) + "_LIST";
+ if (descriptor->is_packed()) {
+ (*variables)["annotation_field_type"] =
+ (*variables)["annotation_field_type"] + "_PACKED";
+ }
+ }
+}
+
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ const OneofGeneratorInfo* info,
+ std::map<std::string, std::string>* variables) {
+ (*variables)["oneof_name"] = info->name;
+ (*variables)["oneof_capitalized_name"] = info->capitalized_name;
+ (*variables)["oneof_index"] =
+ StrCat(descriptor->containing_oneof()->index());
+ (*variables)["oneof_stored_type"] = GetOneofStoredType(descriptor);
+ (*variables)["set_oneof_case_message"] =
+ info->name + "Case_ = " + StrCat(descriptor->number());
+ (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0";
+ (*variables)["has_oneof_case_message"] =
+ info->name + "Case_ == " + StrCat(descriptor->number());
+}
+
+void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables,
+ io::Printer* printer) {
+ const std::map<std::string, std::string>::const_iterator it =
+ variables.find("disambiguated_reason");
+ if (it != variables.end() && !it->second.empty()) {
+ printer->Print(
+ variables,
+ "// An alternative name is used for field \"$field_name$\" because:\n"
+ "// $disambiguated_reason$\n");
+ }
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.h
new file mode 100644
index 00000000..d010faac
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_field.h
@@ -0,0 +1,191 @@
+// 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_JAVA_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableFieldGenerator {
+ public:
+ ImmutableFieldGenerator() {}
+ virtual ~ImmutableFieldGenerator();
+
+ virtual int GetNumBitsForMessage() const = 0;
+ virtual int GetNumBitsForBuilder() const = 0;
+ virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+ virtual void GenerateMembers(io::Printer* printer) const = 0;
+ virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+ virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+ virtual void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const = 0;
+ virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
+
+ virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+ virtual void GenerateHashCode(io::Printer* printer) const = 0;
+
+ virtual std::string GetBoxedType() const = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator);
+};
+
+class ImmutableFieldLiteGenerator {
+ public:
+ ImmutableFieldLiteGenerator() {}
+ virtual ~ImmutableFieldLiteGenerator();
+
+ virtual int GetNumBitsForMessage() const = 0;
+ virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+ virtual void GenerateMembers(io::Printer* printer) const = 0;
+ virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const = 0;
+ virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
+
+ virtual std::string GetBoxedType() const = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
+};
+
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+template <typename FieldGeneratorType>
+class FieldGeneratorMap {
+ public:
+ explicit FieldGeneratorMap(const Descriptor* descriptor, Context* context);
+ ~FieldGeneratorMap();
+
+ const FieldGeneratorType& get(const FieldDescriptor* field) const;
+
+ private:
+ const Descriptor* descriptor_;
+ std::vector<std::unique_ptr<FieldGeneratorType>> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+template <typename FieldGeneratorType>
+inline const FieldGeneratorType& FieldGeneratorMap<FieldGeneratorType>::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+// Instantiate template for mutable and immutable maps.
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context);
+
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap();
+
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context);
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap();
+
+
+// Field information used in FieldGeneartors.
+struct FieldGeneratorInfo {
+ std::string name;
+ std::string capitalized_name;
+ std::string disambiguated_reason;
+};
+
+// Oneof information used in OneofFieldGenerators.
+struct OneofGeneratorInfo {
+ std::string name;
+ std::string capitalized_name;
+};
+
+// Set some common variables used in variable FieldGenerators.
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ const FieldGeneratorInfo* info,
+ std::map<std::string, std::string>* variables);
+
+// Set some common oneof variables used in OneofFieldGenerators.
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ const OneofGeneratorInfo* info,
+ std::map<std::string, std::string>* variables);
+
+// Print useful comments before a field's accessors.
+void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables,
+ io::Printer* printer);
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.cc
new file mode 100644
index 00000000..71a49ed4
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.cc
@@ -0,0 +1,734 @@
+// 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 <compiler/java/java_file.h>
+
+#include <memory>
+#include <set>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_enum.h>
+#include <compiler/java/java_enum_lite.h>
+#include <compiler/java/java_extension.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_message.h>
+#include <compiler/java/java_name_resolver.h>
+#include <compiler/java/java_service.h>
+#include <compiler/java/java_shared_code_generator.h>
+#include <compiler/code_generator.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <dynamic_message.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+struct FieldDescriptorCompare {
+ bool operator()(const FieldDescriptor* f1, const FieldDescriptor* f2) const {
+ if (f1 == NULL) {
+ return false;
+ }
+ if (f2 == NULL) {
+ return true;
+ }
+ return f1->full_name() < f2->full_name();
+ }
+};
+
+typedef std::set<const FieldDescriptor*, FieldDescriptorCompare>
+ FieldDescriptorSet;
+
+// Recursively searches the given message to collect extensions.
+// Returns true if all the extensions can be recognized. The extensions will be
+// 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, FieldDescriptorSet* 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;
+
+ std::vector<const FieldDescriptor*> fields;
+ reflection->ListFields(message, &fields);
+
+ for (int i = 0; i < fields.size(); i++) {
+ if (fields[i]->is_extension()) {
+ extensions->insert(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,
+ FieldDescriptorSet* extensions,
+ const std::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;
+ std::unique_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.";
+ }
+}
+
+// Our static initialization methods can become very, very large.
+// So large that if we aren't careful we end up blowing the JVM's
+// 64K bytes of bytecode/method. Fortunately, since these static
+// methods are executed only once near the beginning of a program,
+// there's usually plenty of stack space available and we can
+// extend our methods by simply chaining them to another method
+// with a tail call. This inserts the sequence call-next-method,
+// end this one, begin-next-method as needed.
+void MaybeRestartJavaMethod(io::Printer* printer, int* bytecode_estimate,
+ int* method_num, const char* chain_statement,
+ const char* method_decl) {
+ // The goal here is to stay under 64K bytes of jvm bytecode/method,
+ // since otherwise we hit a hardcoded limit in the jvm and javac will
+ // then fail with the error "code too large". This limit lets our
+ // estimates be off by a factor of two and still we're okay.
+ static const int bytesPerMethod = kMaxStaticSize;
+
+ if ((*bytecode_estimate) > bytesPerMethod) {
+ ++(*method_num);
+ printer->Print(chain_statement, "method_num", StrCat(*method_num));
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(method_decl, "method_num", StrCat(*method_num));
+ printer->Indent();
+ *bytecode_estimate = 0;
+ }
+}
+} // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options,
+ bool immutable_api)
+ : file_(file),
+ java_package_(FileJavaPackage(file, immutable_api)),
+ message_generators_(file->message_type_count()),
+ extension_generators_(file->extension_count()),
+ context_(new Context(file, options)),
+ name_resolver_(context_->GetNameResolver()),
+ options_(options),
+ immutable_api_(immutable_api) {
+ classname_ = name_resolver_->GetFileClassName(file, immutable_api);
+ generator_factory_.reset(new ImmutableGeneratorFactory(context_.get()));
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ message_generators_[i].reset(
+ generator_factory_->NewMessageGenerator(file_->message_type(i)));
+ }
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ extension_generators_[i].reset(
+ generator_factory_->NewExtensionGenerator(file_->extension(i)));
+ }
+}
+
+FileGenerator::~FileGenerator() {}
+
+bool FileGenerator::Validate(std::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.
+ if (name_resolver_->HasConflictingClassName(file_, classname_,
+ NameEquality::EXACT_EQUAL)) {
+ 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;
+ }
+ // Similar to the check above, but ignore the case this time. This is not a
+ // problem on Linux, but will lead to Java compile errors on Windows / Mac
+ // because filenames are case-insensitive on those platforms.
+ if (name_resolver_->HasConflictingClassName(
+ file_, classname_, NameEquality::EQUAL_IGNORE_CASE)) {
+ GOOGLE_LOG(WARNING)
+ << file_->name() << ": The file's outer class name, \"" << classname_
+ << "\", matches the name of one of the types declared inside it when "
+ << "case is ignored. This can cause compilation issues on Windows / "
+ << "MacOS. Please either rename the type or use the "
+ << "java_outer_classname option to specify a different outer class "
+ << "name for the .proto file to be safe.";
+ }
+
+ // Print a warning if optimize_for = LITE_RUNTIME is used.
+ if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+ !options_.enforce_lite) {
+ GOOGLE_LOG(WARNING)
+ << "The optimize_for = LITE_RUNTIME option is no longer supported by "
+ << "protobuf Java code generator and is ignored--protoc will always "
+ << "generate full runtime code for Java. To use Java Lite runtime, "
+ << "users should use the Java Lite plugin instead. See:\n"
+ << " "
+ "https://github.com/protocolbuffers/protobuf/blob/master/java/"
+ "lite.md";
+ }
+ 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_);
+ }
+ PrintGeneratedAnnotation(
+ printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : "");
+
+ printer->Print(
+ "$deprecation$public final class $classname$ {\n"
+ " private $ctor$() {}\n",
+ "deprecation",
+ file_->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "classname", classname_, "ctor", classname_);
+ printer->Annotate("classname", file_->name());
+ printer->Indent();
+
+ // -----------------------------------------------------------------
+
+ printer->Print(
+ "public static void registerAllExtensions(\n"
+ " com.google.protobuf.ExtensionRegistryLite registry) {\n");
+
+ printer->Indent();
+
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateRegistrationCode(printer);
+ }
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateExtensionRegistrationCode(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+ // Overload registerAllExtensions for the non-lite usage to
+ // redundantly maintain the original signature (this is
+ // redundant because ExtensionRegistryLite now invokes
+ // ExtensionRegistry in the non-lite usage). Intent is
+ // to remove this in the future.
+ printer->Print(
+ "\n"
+ "public static void registerAllExtensions(\n"
+ " com.google.protobuf.ExtensionRegistry registry) {\n"
+ " registerAllExtensions(\n"
+ " (com.google.protobuf.ExtensionRegistryLite) registry);\n"
+ "}\n");
+ }
+
+ // -----------------------------------------------------------------
+
+ if (!MultipleJavaFiles(file_, immutable_api_)) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+ EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
+ .Generate(printer);
+ } else {
+ EnumLiteGenerator(file_->enum_type(i), immutable_api_, context_.get())
+ .Generate(printer);
+ }
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateInterface(printer);
+ message_generators_[i]->Generate(printer);
+ }
+ if (HasGenericServices(file_, context_->EnforceLite())) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ std::unique_ptr<ServiceGenerator> generator(
+ generator_factory_->NewServiceGenerator(file_->service(i)));
+ generator->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++) {
+ extension_generators_[i]->Generate(printer);
+ }
+
+ // Static variables. We'd like them to be final if possible, but due to
+ // the JVM's 64k size limit on static blocks, we have to initialize some
+ // of them in methods; thus they cannot be final.
+ int static_block_bytecode_estimate = 0;
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateStaticVariables(
+ printer, &static_block_bytecode_estimate);
+ }
+
+ printer->Print("\n");
+
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+ if (immutable_api_) {
+ GenerateDescriptorInitializationCodeForImmutable(printer);
+ } else {
+ GenerateDescriptorInitializationCodeForMutable(printer);
+ }
+ } else {
+ printer->Print("static {\n");
+ printer->Indent();
+ int bytecode_estimate = 0;
+ int method_num = 0;
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ bytecode_estimate +=
+ message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer, &bytecode_estimate, &method_num,
+ "_clinit_autosplit_$method_num$();\n",
+ "private static void _clinit_autosplit_$method_num$() {\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(outer_class_scope)\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.Descriptors.FileDescriptor\n"
+ " getDescriptor() {\n"
+ " return descriptor;\n"
+ "}\n"
+ "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
+ " descriptor;\n"
+ "static {\n",
+ // TODO(dweis): Mark this as final.
+ "final", "");
+ printer->Indent();
+
+ SharedCodeGenerator shared_code_generator(file_, options_);
+ shared_code_generator.GenerateDescriptors(printer);
+
+ int bytecode_estimate = 0;
+ int method_num = 0;
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ bytecode_estimate +=
+ message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer, &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ bytecode_estimate +=
+ extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ MaybeRestartJavaMethod(
+ printer, &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
+ }
+
+ // Proto compiler builds a DescriptorPool, which holds all the descriptors to
+ // 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
+ FileDescriptorProto file_proto;
+ file_->CopyTo(&file_proto);
+ std::string file_data;
+ file_proto.SerializeToString(&file_data);
+ FieldDescriptorSet extensions;
+ CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+ if (extensions.size() > 0) {
+ // Must construct an ExtensionRegistry containing all existing extensions
+ // and use it to parse the descriptor data again to recognize extensions.
+ printer->Print(
+ "com.google.protobuf.ExtensionRegistry registry =\n"
+ " com.google.protobuf.ExtensionRegistry.newInstance();\n");
+ FieldDescriptorSet::iterator it;
+ for (it = extensions.begin(); it != extensions.end(); it++) {
+ std::unique_ptr<ExtensionGenerator> generator(
+ generator_factory_->NewExtensionGenerator(*it));
+ bytecode_estimate += generator->GenerateRegistrationCode(printer);
+ MaybeRestartJavaMethod(
+ printer, &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$(registry);\n",
+ "private static void _clinit_autosplit_dinit_$method_num$(\n"
+ " com.google.protobuf.ExtensionRegistry registry) {\n");
+ }
+ printer->Print(
+ "com.google.protobuf.Descriptors.FileDescriptor\n"
+ " .internalUpdateFileDescriptor(descriptor, registry);\n");
+ }
+
+ // Force descriptor initialization of all dependencies.
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ if (ShouldIncludeDependency(file_->dependency(i), true)) {
+ std::string dependency =
+ name_resolver_->GetImmutableClassName(file_->dependency(i));
+ printer->Print("$dependency$.getDescriptor();\n", "dependency",
+ dependency);
+ }
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void FileGenerator::GenerateDescriptorInitializationCodeForMutable(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.Descriptors.FileDescriptor\n"
+ " getDescriptor() {\n"
+ " return descriptor;\n"
+ "}\n"
+ "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
+ " descriptor;\n"
+ "static {\n");
+ printer->Indent();
+
+ printer->Print(
+ "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n",
+ "immutable_package", FileJavaPackage(file_, true), "descriptor_classname",
+ name_resolver_->GetDescriptorClassName(file_));
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ }
+
+ // Check if custom options exist. If any, try to load immutable classes since
+ // custom options are only represented with immutable messages.
+ FileDescriptorProto file_proto;
+ file_->CopyTo(&file_proto);
+ std::string file_data;
+ file_proto.SerializeToString(&file_data);
+ FieldDescriptorSet extensions;
+ CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+ if (extensions.size() > 0) {
+ // Try to load immutable messages' outer class. Its initialization code
+ // will take care of interpreting custom options.
+ printer->Print(
+ "try {\n"
+ // Note that we have to load the immutable class dynamically here as
+ // we want the mutable code to be independent from the immutable code
+ // at compile time. It is required to implement dual-compile for
+ // mutable and immutable API in blaze.
+ " java.lang.Class<?> immutableClass = java.lang.Class.forName(\n"
+ " \"$immutable_classname$\");\n"
+ "} catch (java.lang.ClassNotFoundException e) {\n",
+ "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+ printer->Indent();
+
+ // The immutable class can not be found. We try our best to collect all
+ // custom option extensions to interpret the custom options.
+ printer->Print(
+ "com.google.protobuf.ExtensionRegistry registry =\n"
+ " com.google.protobuf.ExtensionRegistry.newInstance();\n"
+ "com.google.protobuf.MessageLite defaultExtensionInstance = null;\n");
+ FieldDescriptorSet::iterator it;
+ for (it = extensions.begin(); it != extensions.end(); it++) {
+ const FieldDescriptor* field = *it;
+ std::string scope;
+ if (field->extension_scope() != NULL) {
+ scope = name_resolver_->GetMutableClassName(field->extension_scope()) +
+ ".getDescriptor()";
+ } else {
+ scope = FileJavaPackage(field->file(), true) + "." +
+ name_resolver_->GetDescriptorClassName(field->file()) +
+ ".descriptor";
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ "defaultExtensionInstance = com.google.protobuf.Internal\n"
+ " .getDefaultInstance(\"$class$\");\n"
+ "if (defaultExtensionInstance != null) {\n"
+ " registry.add(\n"
+ " $scope$.getExtensions().get($index$),\n"
+ " (com.google.protobuf.Message) defaultExtensionInstance);\n"
+ "}\n",
+ "scope", scope, "index", StrCat(field->index()), "class",
+ name_resolver_->GetImmutableClassName(field->message_type()));
+ } else {
+ printer->Print("registry.add($scope$.getExtensions().get($index$));\n",
+ "scope", scope, "index", StrCat(field->index()));
+ }
+ }
+ printer->Print(
+ "com.google.protobuf.Descriptors.FileDescriptor\n"
+ " .internalUpdateFileDescriptor(descriptor, registry);\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ // Force descriptor initialization of all dependencies.
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ if (ShouldIncludeDependency(file_->dependency(i), false)) {
+ std::string dependency =
+ name_resolver_->GetMutableClassName(file_->dependency(i));
+ printer->Print("$dependency$.getDescriptor();\n", "dependency",
+ dependency);
+ }
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+template <typename GeneratorClass, typename DescriptorClass>
+static void GenerateSibling(
+ const std::string& package_dir, const std::string& java_package,
+ const DescriptorClass* descriptor, GeneratorContext* context,
+ std::vector<std::string>* file_list, bool annotate_code,
+ std::vector<std::string>* annotation_list, const std::string& name_suffix,
+ GeneratorClass* generator,
+ void (GeneratorClass::*pfn)(io::Printer* printer)) {
+ std::string filename =
+ package_dir + descriptor->name() + name_suffix + ".java";
+ file_list->push_back(filename);
+ std::string info_full_path = filename + ".pb.meta";
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ io::Printer printer(output.get(), '$',
+ annotate_code ? &annotation_collector : NULL);
+
+ 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);
+ }
+
+ (generator->*pfn)(&printer);
+
+ if (annotate_code) {
+ std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+ context->Open(info_full_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ annotation_list->push_back(info_full_path);
+ }
+}
+
+void FileGenerator::GenerateSiblings(
+ const std::string& package_dir, GeneratorContext* context,
+ std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_list) {
+ if (MultipleJavaFiles(file_, immutable_api_)) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+ EnumGenerator generator(file_->enum_type(i), immutable_api_,
+ context_.get());
+ GenerateSibling<EnumGenerator>(
+ package_dir, java_package_, file_->enum_type(i), context, file_list,
+ options_.annotate_code, annotation_list, "", &generator,
+ &EnumGenerator::Generate);
+ } else {
+ EnumLiteGenerator generator(file_->enum_type(i), immutable_api_,
+ context_.get());
+ GenerateSibling<EnumLiteGenerator>(
+ package_dir, java_package_, file_->enum_type(i), context, file_list,
+ options_.annotate_code, annotation_list, "", &generator,
+ &EnumLiteGenerator::Generate);
+ }
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (immutable_api_) {
+ GenerateSibling<MessageGenerator>(
+ package_dir, java_package_, file_->message_type(i), context,
+ file_list, options_.annotate_code, annotation_list, "OrBuilder",
+ message_generators_[i].get(), &MessageGenerator::GenerateInterface);
+ }
+ GenerateSibling<MessageGenerator>(
+ package_dir, java_package_, file_->message_type(i), context,
+ file_list, options_.annotate_code, annotation_list, "",
+ message_generators_[i].get(), &MessageGenerator::Generate);
+ }
+ if (HasGenericServices(file_, context_->EnforceLite())) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ std::unique_ptr<ServiceGenerator> generator(
+ generator_factory_->NewServiceGenerator(file_->service(i)));
+ GenerateSibling<ServiceGenerator>(
+ package_dir, java_package_, file_->service(i), context, file_list,
+ options_.annotate_code, annotation_list, "", generator.get(),
+ &ServiceGenerator::Generate);
+ }
+ }
+ }
+}
+
+std::string FileGenerator::GetKotlinClassname() {
+ return name_resolver_->GetFileClassName(file_, immutable_api_, true);
+}
+
+void FileGenerator::GenerateKotlinSiblings(
+ const std::string& package_dir, GeneratorContext* context,
+ std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_list) {
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ const Descriptor* descriptor = file_->message_type(i);
+ MessageGenerator* generator = message_generators_[i].get();
+ auto open_file = [context](const std::string& filename) {
+ return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
+ };
+ std::string filename = package_dir + descriptor->name() + "Kt.kt";
+ file_list->push_back(filename);
+ std::string info_full_path = filename + ".pb.meta";
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ auto output = open_file(filename);
+ io::Printer printer(
+ output.get(), '$',
+ options_.annotate_code ? &annotation_collector : nullptr);
+
+ 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_);
+ }
+
+ generator->GenerateKotlinMembers(&printer);
+ generator->GenerateTopLevelKotlinMembers(&printer);
+
+ if (options_.annotate_code) {
+ auto info_output = open_file(info_full_path);
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ annotation_list->push_back(info_full_path);
+ }
+ }
+}
+
+bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor,
+ bool immutable_api) {
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.h
new file mode 100644
index 00000000..80fb6e5d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_file.h
@@ -0,0 +1,125 @@
+// 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_JAVA_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <stubs/common.h>
+#include <compiler/java/java_options.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+namespace compiler {
+class GeneratorContext; // code_generator.h
+namespace java {
+class Context; // context.h
+class MessageGenerator; // message.h
+class GeneratorFactory; // generator_factory.h
+class ExtensionGenerator; // extension.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class FileGenerator {
+ public:
+ FileGenerator(const FileDescriptor* file, const Options& options,
+ bool immutable_api = true);
+ ~FileGenerator();
+
+ // Checks for problems that would otherwise lead to cryptic compile errors.
+ // Returns true if there are no problems, or writes an error description to
+ // the given string and returns false otherwise.
+ bool Validate(std::string* error);
+
+ void Generate(io::Printer* printer);
+
+ std::string GetKotlinClassname();
+ void GenerateKotlinSiblings(const std::string& package_dir,
+ GeneratorContext* generator_context,
+ std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_list);
+
+ // If we aren't putting everything into one file, this will write all the
+ // files other than the outer file (i.e. one for each message, enum, and
+ // service type).
+ void GenerateSiblings(const std::string& package_dir,
+ GeneratorContext* generator_context,
+ std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_list);
+
+ const std::string& java_package() { return java_package_; }
+ const std::string& classname() { return classname_; }
+
+ private:
+ void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer);
+ void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer);
+
+ bool ShouldIncludeDependency(const FileDescriptor* descriptor,
+ bool immutable_api_);
+
+ const FileDescriptor* file_;
+ std::string java_package_;
+ std::string classname_;
+
+ std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
+ std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+ std::unique_ptr<GeneratorFactory> generator_factory_;
+ std::unique_ptr<Context> context_;
+ ClassNameResolver* name_resolver_;
+ const Options options_;
+ bool immutable_api_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.cc
new file mode 100644
index 00000000..611a4d9c
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.cc
@@ -0,0 +1,211 @@
+// 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 <compiler/java/java_generator.h>
+
+
+#include <memory>
+
+#include <compiler/java/java_file.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <compiler/java/java_options.h>
+#include <compiler/java/java_shared_code_generator.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+
+JavaGenerator::JavaGenerator() {}
+JavaGenerator::~JavaGenerator() {}
+
+uint64_t JavaGenerator::GetSupportedFeatures() const {
+ return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
+bool JavaGenerator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* context,
+ std::string* error) const {
+ // -----------------------------------------------------------------
+ // parse generator options
+
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+ Options file_options;
+
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "output_list_file") {
+ file_options.output_list_file = options[i].second;
+ } else if (options[i].first == "immutable") {
+ file_options.generate_immutable_code = true;
+ } else if (options[i].first == "mutable") {
+ file_options.generate_mutable_code = true;
+ } else if (options[i].first == "shared") {
+ file_options.generate_shared_code = true;
+ } else if (options[i].first == "lite") {
+ // Note: Java Lite does not guarantee API/ABI stability. We may choose to
+ // break existing API in order to boost performance / reduce code size.
+ file_options.enforce_lite = true;
+ } else if (options[i].first == "annotate_code") {
+ file_options.annotate_code = true;
+ } else if (options[i].first == "annotation_list_file") {
+ file_options.annotation_list_file = options[i].second;
+ } else {
+ *error = "Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ if (file_options.enforce_lite && file_options.generate_mutable_code) {
+ *error = "lite runtime generator option cannot be used with mutable API.";
+ return false;
+ }
+
+ // By default we generate immutable code and shared code for immutable API.
+ if (!file_options.generate_immutable_code &&
+ !file_options.generate_mutable_code &&
+ !file_options.generate_shared_code) {
+ file_options.generate_immutable_code = true;
+ file_options.generate_shared_code = true;
+ }
+
+ // -----------------------------------------------------------------
+
+
+ std::vector<std::string> all_files;
+ std::vector<std::string> all_annotations;
+
+
+ std::vector<FileGenerator*> file_generators;
+ if (file_options.generate_immutable_code) {
+ file_generators.push_back(new FileGenerator(file, file_options,
+ /* immutable = */ true));
+ }
+ if (file_options.generate_mutable_code) {
+ file_generators.push_back(new FileGenerator(file, file_options,
+ /* mutable = */ false));
+ }
+
+ for (int i = 0; i < file_generators.size(); ++i) {
+ if (!file_generators[i]->Validate(error)) {
+ for (int j = 0; j < file_generators.size(); ++j) {
+ delete file_generators[j];
+ }
+ return false;
+ }
+ }
+
+ for (int i = 0; i < file_generators.size(); ++i) {
+ FileGenerator* file_generator = file_generators[i];
+
+ std::string package_dir = JavaPackageToDir(file_generator->java_package());
+
+ std::string java_filename = package_dir;
+ java_filename += file_generator->classname();
+ java_filename += ".java";
+ all_files.push_back(java_filename);
+ std::string info_full_path = java_filename + ".pb.meta";
+ if (file_options.annotate_code) {
+ all_annotations.push_back(info_full_path);
+ }
+
+ // Generate main java file.
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(java_filename));
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ file_options.annotate_code ? &annotation_collector : NULL);
+
+ file_generator->Generate(&printer);
+
+ // Generate sibling files.
+ file_generator->GenerateSiblings(package_dir, context, &all_files,
+ &all_annotations);
+
+ if (file_options.annotate_code) {
+ std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+ context->Open(info_full_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
+ }
+
+
+ for (int i = 0; i < file_generators.size(); ++i) {
+ delete file_generators[i];
+ }
+ file_generators.clear();
+
+ // Generate output list if requested.
+ if (!file_options.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.
+ std::unique_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+ context->Open(file_options.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]);
+ }
+ }
+
+ if (!file_options.annotation_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.
+ std::unique_ptr<io::ZeroCopyOutputStream> annotation_list_raw_output(
+ context->Open(file_options.annotation_list_file));
+ io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
+ for (int i = 0; i < all_annotations.size(); i++) {
+ annotation_list_printer.Print("$filename$\n", "filename",
+ all_annotations[i]);
+ }
+ }
+
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.h
new file mode 100644
index 00000000..7910cc03
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator.h
@@ -0,0 +1,76 @@
+// 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.
+//
+// Generates Java code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
+
+#include <string>
+#include <compiler/code_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// CodeGenerator implementation which generates Java code. If you create your
+// own protocol compiler binary and you want it to support Java output, you
+// can do so by registering an instance of this CodeGenerator with the
+// CommandLineInterface in your main() function.
+class PROTOC_EXPORT JavaGenerator : public CodeGenerator {
+ public:
+ JavaGenerator();
+ ~JavaGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.cc
new file mode 100644
index 00000000..50fa50b0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.cc
@@ -0,0 +1,86 @@
+// 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: liujisi@google.com (Pherl Liu)
+
+#include <compiler/java/java_generator_factory.h>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_enum_field.h>
+#include <compiler/java/java_extension.h>
+#include <compiler/java/java_extension_lite.h>
+#include <compiler/java/java_field.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_message.h>
+#include <compiler/java/java_message_lite.h>
+#include <compiler/java/java_service.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+GeneratorFactory::GeneratorFactory() {}
+GeneratorFactory::~GeneratorFactory() {}
+
+// ===================================================================
+
+ImmutableGeneratorFactory::ImmutableGeneratorFactory(Context* context)
+ : context_(context) {}
+ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {}
+
+MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
+ const Descriptor* descriptor) const {
+ if (HasDescriptorMethods(descriptor, context_->EnforceLite())) {
+ return new ImmutableMessageGenerator(descriptor, context_);
+ } else {
+ return new ImmutableMessageLiteGenerator(descriptor, context_);
+ }
+}
+
+ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
+ const FieldDescriptor* descriptor) const {
+ if (HasDescriptorMethods(descriptor->file(), context_->EnforceLite())) {
+ return new ImmutableExtensionGenerator(descriptor, context_);
+ } else {
+ return new ImmutableExtensionLiteGenerator(descriptor, context_);
+ }
+}
+
+ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator(
+ const ServiceDescriptor* descriptor) const {
+ return new ImmutableServiceGenerator(descriptor, context_);
+}
+
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.h
new file mode 100644
index 00000000..a0a827a5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_generator_factory.h
@@ -0,0 +1,103 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
+
+#include <stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor; // descriptor.h
+class Descriptor; // descriptor.h
+class ServiceDescriptor; // descriptor.h
+namespace compiler {
+namespace java {
+class MessageGenerator; // message.h
+class ExtensionGenerator; // extension.h
+class ServiceGenerator; // service.h
+class Context; // context.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class GeneratorFactory {
+ public:
+ GeneratorFactory();
+ virtual ~GeneratorFactory();
+
+ virtual MessageGenerator* NewMessageGenerator(
+ const Descriptor* descriptor) const = 0;
+
+ virtual ExtensionGenerator* NewExtensionGenerator(
+ const FieldDescriptor* descriptor) const = 0;
+
+ virtual ServiceGenerator* NewServiceGenerator(
+ const ServiceDescriptor* descriptor) const = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory);
+};
+
+// Factory that creates generators for immutable-default messages.
+class ImmutableGeneratorFactory : public GeneratorFactory {
+ public:
+ ImmutableGeneratorFactory(Context* context);
+ virtual ~ImmutableGeneratorFactory();
+
+ MessageGenerator* NewMessageGenerator(
+ const Descriptor* descriptor) const override;
+
+ ExtensionGenerator* NewExtensionGenerator(
+ const FieldDescriptor* descriptor) const override;
+
+ ServiceGenerator* NewServiceGenerator(
+ const ServiceDescriptor* descriptor) const override;
+
+ private:
+ Context* context_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory);
+};
+
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.cc
new file mode 100644
index 00000000..0ce86ba9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.cc
@@ -0,0 +1,1100 @@
+// 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 <compiler/java/java_helpers.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <limits>
+#include <unordered_set>
+#include <vector>
+
+#include <stubs/stringprintf.h>
+#include <compiler/java/java_name_resolver.h>
+#include <compiler/java/java_names.h>
+#include <descriptor.pb.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+#include <stubs/hash.h> // for hash<T *>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+const char kThickSeparator[] =
+ "// ===================================================================\n";
+const char kThinSeparator[] =
+ "// -------------------------------------------------------------------\n";
+
+namespace {
+
+const char* kDefaultPackage = "";
+
+// Names that should be avoided as field names.
+// Using them will cause the compiler to generate accessors whose names are
+// colliding with methods defined in base classes.
+const char* kForbiddenWordList[] = {
+ // message base class:
+ "cached_size",
+ "serialized_size",
+ // java.lang.Object:
+ "class",
+};
+
+const std::unordered_set<std::string>* kReservedNames =
+ new std::unordered_set<std::string>({
+ "abstract", "assert", "boolean", "break", "byte",
+ "case", "catch", "char", "class", "const",
+ "continue", "default", "do", "double", "else",
+ "enum", "extends", "final", "finally", "float",
+ "for", "goto", "if", "implements", "import",
+ "instanceof", "int", "interface", "long", "native",
+ "new", "package", "private", "protected", "public",
+ "return", "short", "static", "strictfp", "super",
+ "switch", "synchronized", "this", "throw", "throws",
+ "transient", "try", "void", "volatile", "while",
+ });
+
+bool IsForbidden(const std::string& field_name) {
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
+ if (field_name == kForbiddenWordList[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string FieldName(const FieldDescriptor* field) {
+ std::string field_name;
+ // Groups are hacky: The name of the field is just the lower-cased name
+ // of the group type. In Java, though, we would like to retain the original
+ // capitalization of the type name.
+ if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
+ field_name = field->message_type()->name();
+ } else {
+ field_name = field->name();
+ }
+ if (IsForbidden(field_name)) {
+ // Append a trailing "#" to indicate that the name should be decorated to
+ // avoid collision with other names.
+ field_name += "#";
+ }
+ return field_name;
+}
+
+
+} // namespace
+
+void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
+ const std::string& annotation_file) {
+ if (annotation_file.empty()) {
+ return;
+ }
+ std::string ptemplate =
+ "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:";
+ ptemplate.push_back(delimiter);
+ ptemplate.append("annotation_file");
+ ptemplate.push_back(delimiter);
+ ptemplate.append("\")\n");
+ printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
+}
+
+void PrintEnumVerifierLogic(io::Printer* printer,
+ const FieldDescriptor* descriptor,
+ const std::map<std::string, std::string>& variables,
+ const char* var_name,
+ const char* terminating_string, bool enforce_lite) {
+ std::string enum_verifier_string =
+ enforce_lite ? StrCat(var_name, ".internalGetVerifier()")
+ : StrCat(
+ "new com.google.protobuf.Internal.EnumVerifier() {\n"
+ " @java.lang.Override\n"
+ " public boolean isInRange(int number) {\n"
+ " return ",
+ var_name,
+ ".forNumber(number) != null;\n"
+ " }\n"
+ " }");
+ printer->Print(
+ variables,
+ StrCat(enum_verifier_string, terminating_string).c_str());
+}
+
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool cap_next_letter) {
+ GOOGLE_CHECK(!input.empty());
+ std::string result;
+ // Note: I distrust ctype.h due to locales.
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_next_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ if (i == 0 && !cap_next_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += input[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += input[i];
+ }
+ cap_next_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_next_letter = true;
+ } else {
+ cap_next_letter = true;
+ }
+ }
+ // Add a trailing "_" if the name should be altered.
+ if (input[input.size() - 1] == '#') {
+ result += '_';
+ }
+ return result;
+}
+
+std::string ToCamelCase(const std::string& input, bool lower_first) {
+ bool capitalize_next = !lower_first;
+ std::string result;
+ result.reserve(input.size());
+
+ for (char i : input) {
+ if (i == '_') {
+ capitalize_next = true;
+ } else if (capitalize_next) {
+ result.push_back(ToUpperCh(i));
+ capitalize_next = false;
+ } else {
+ result.push_back(i);
+ }
+ }
+
+ // Lower-case the first letter.
+ if (lower_first && !result.empty()) {
+ result[0] = ToLowerCh(result[0]);
+ }
+
+ return result;
+}
+
+char ToUpperCh(char ch) {
+ return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
+}
+
+char ToLowerCh(char ch) {
+ return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
+}
+
+std::string UnderscoresToCamelCase(const FieldDescriptor* field) {
+ return UnderscoresToCamelCase(FieldName(field), false);
+}
+
+std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
+ return UnderscoresToCamelCase(FieldName(field), true);
+}
+
+std::string CapitalizedFieldName(const FieldDescriptor* field) {
+ return UnderscoresToCapitalizedCamelCase(field);
+}
+
+std::string UnderscoresToCamelCase(const MethodDescriptor* method) {
+ return UnderscoresToCamelCase(method->name(), false);
+}
+
+std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
+ std::string name = UnderscoresToCamelCase(field);
+ if (kReservedNames->find(name) != kReservedNames->end()) {
+ return name + "_";
+ }
+ return name;
+}
+
+bool IsForbiddenKotlin(const std::string& field_name) {
+ // Names that should be avoided as field names in Kotlin.
+ // All Kotlin hard keywords are in this list.
+ const std::unordered_set<std::string>* kKotlinForbiddenNames =
+ new std::unordered_set<std::string>({
+ "as", "as?", "break", "class", "continue", "do",
+ "else", "false", "for", "fun", "if", "in",
+ "!in", "interface", "is", "!is", "null", "object",
+ "package", "return", "super", "this", "throw", "true",
+ "try", "typealias", "typeof", "val", "var", "when",
+ "while",
+ });
+ return kKotlinForbiddenNames->find(field_name) !=
+ kKotlinForbiddenNames->end();
+}
+
+std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
+ return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
+}
+
+std::string CamelCaseFieldName(const FieldDescriptor* field) {
+ std::string fieldName = UnderscoresToCamelCase(field);
+ if ('0' <= fieldName[0] && fieldName[0] <= '9') {
+ return '_' + fieldName;
+ }
+ return fieldName;
+}
+
+std::string FileClassName(const FileDescriptor* file, bool immutable) {
+ ClassNameResolver name_resolver;
+ return name_resolver.GetFileClassName(file, immutable);
+}
+
+std::string FileJavaPackage(const FileDescriptor* file, bool immutable) {
+ std::string result;
+
+ if (file->options().has_java_package()) {
+ result = file->options().java_package();
+ } else {
+ result = kDefaultPackage;
+ if (!file->package().empty()) {
+ if (!result.empty()) result += '.';
+ result += file->package();
+ }
+ }
+
+ return result;
+}
+
+std::string FileJavaPackage(const FileDescriptor* file) {
+ return FileJavaPackage(file, true /* immutable */);
+}
+
+std::string JavaPackageToDir(std::string package_name) {
+ std::string package_dir = StringReplace(package_name, ".", "/", true);
+ if (!package_dir.empty()) package_dir += "/";
+ return package_dir;
+}
+
+std::string ClassName(const Descriptor* descriptor) {
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const EnumDescriptor* descriptor) {
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const ServiceDescriptor* descriptor) {
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const FileDescriptor* descriptor) {
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
+}
+
+
+std::string ExtraMessageInterfaces(const Descriptor* descriptor) {
+ std::string interfaces = "// @@protoc_insertion_point(message_implements:" +
+ descriptor->full_name() + ")";
+ return interfaces;
+}
+
+
+std::string ExtraBuilderInterfaces(const Descriptor* descriptor) {
+ std::string interfaces = "// @@protoc_insertion_point(builder_implements:" +
+ descriptor->full_name() + ")";
+ return interfaces;
+}
+
+std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
+ std::string interfaces = "// @@protoc_insertion_point(interface_extends:" +
+ descriptor->full_name() + ")";
+ return interfaces;
+}
+
+std::string FieldConstantName(const FieldDescriptor* field) {
+ std::string name = field->name() + "_FIELD_NUMBER";
+ ToUpper(&name);
+ return name;
+}
+
+FieldDescriptor::Type GetType(const FieldDescriptor* field) {
+ return field->type();
+}
+
+JavaType GetJavaType(const FieldDescriptor* field) {
+ switch (GetType(field)) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ return JAVATYPE_INT;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ return JAVATYPE_LONG;
+
+ case FieldDescriptor::TYPE_FLOAT:
+ return JAVATYPE_FLOAT;
+
+ case FieldDescriptor::TYPE_DOUBLE:
+ return JAVATYPE_DOUBLE;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return JAVATYPE_BOOLEAN;
+
+ case FieldDescriptor::TYPE_STRING:
+ return JAVATYPE_STRING;
+
+ case FieldDescriptor::TYPE_BYTES:
+ return JAVATYPE_BYTES;
+
+ case FieldDescriptor::TYPE_ENUM:
+ return JAVATYPE_ENUM;
+
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ return JAVATYPE_MESSAGE;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return JAVATYPE_INT;
+}
+
+const char* PrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT:
+ return "int";
+ case JAVATYPE_LONG:
+ return "long";
+ case JAVATYPE_FLOAT:
+ return "float";
+ case JAVATYPE_DOUBLE:
+ return "double";
+ case JAVATYPE_BOOLEAN:
+ return "boolean";
+ case JAVATYPE_STRING:
+ return "java.lang.String";
+ case JAVATYPE_BYTES:
+ return "com.google.protobuf.ByteString";
+ case JAVATYPE_ENUM:
+ return NULL;
+ case JAVATYPE_MESSAGE:
+ return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
+ return PrimitiveTypeName(GetJavaType(descriptor));
+}
+
+const char* BoxedPrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT:
+ return "java.lang.Integer";
+ case JAVATYPE_LONG:
+ return "java.lang.Long";
+ case JAVATYPE_FLOAT:
+ return "java.lang.Float";
+ case JAVATYPE_DOUBLE:
+ return "java.lang.Double";
+ case JAVATYPE_BOOLEAN:
+ return "java.lang.Boolean";
+ case JAVATYPE_STRING:
+ return "java.lang.String";
+ case JAVATYPE_BYTES:
+ return "com.google.protobuf.ByteString";
+ case JAVATYPE_ENUM:
+ return NULL;
+ case JAVATYPE_MESSAGE:
+ return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor));
+}
+
+const char* KotlinTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT:
+ return "kotlin.Int";
+ case JAVATYPE_LONG:
+ return "kotlin.Long";
+ case JAVATYPE_FLOAT:
+ return "kotlin.Float";
+ case JAVATYPE_DOUBLE:
+ return "kotlin.Double";
+ case JAVATYPE_BOOLEAN:
+ return "kotlin.Boolean";
+ case JAVATYPE_STRING:
+ return "kotlin.String";
+ case JAVATYPE_BYTES:
+ return "com.google.protobuf.ByteString";
+ case JAVATYPE_ENUM:
+ return NULL;
+ case JAVATYPE_MESSAGE:
+ return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+std::string GetOneofStoredType(const FieldDescriptor* field) {
+ const JavaType javaType = GetJavaType(field);
+ switch (javaType) {
+ case JAVATYPE_ENUM:
+ return "java.lang.Integer";
+ case JAVATYPE_MESSAGE:
+ return ClassName(field->message_type());
+ default:
+ return BoxedPrimitiveTypeName(javaType);
+ }
+}
+
+const char* FieldTypeName(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;
+}
+
+bool AllAscii(const std::string& text) {
+ for (int i = 0; i < text.size(); i++) {
+ if ((text[i] & 0x80) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string DefaultValue(const FieldDescriptor* field, bool immutable,
+ ClassNameResolver* name_resolver) {
+ // Switch on CppType since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return StrCat(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ // Need to print as a signed int since Java has no unsigned.
+ return StrCat(static_cast<int32_t>(field->default_value_uint32()));
+ case FieldDescriptor::CPPTYPE_INT64:
+ return StrCat(field->default_value_int64()) + "L";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return StrCat(static_cast<int64_t>(field->default_value_uint64())) +
+ "L";
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == std::numeric_limits<double>::infinity()) {
+ return "Double.POSITIVE_INFINITY";
+ } else if (value == -std::numeric_limits<double>::infinity()) {
+ return "Double.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Double.NaN";
+ } else {
+ return SimpleDtoa(value) + "D";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field->default_value_float();
+ if (value == std::numeric_limits<float>::infinity()) {
+ return "Float.POSITIVE_INFINITY";
+ } else if (value == -std::numeric_limits<float>::infinity()) {
+ return "Float.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Float.NaN";
+ } else {
+ return SimpleFtoa(value) + "F";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
+ if (field->has_default_value()) {
+ // See comments in Internal.java for gory details.
+ return strings::Substitute(
+ "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
+ CEscape(field->default_value_string()));
+ } else {
+ return "com.google.protobuf.ByteString.EMPTY";
+ }
+ } else {
+ if (AllAscii(field->default_value_string())) {
+ // All chars are ASCII. In this case CEscape() works fine.
+ return "\"" + CEscape(field->default_value_string()) + "\"";
+ } else {
+ // See comments in Internal.java for gory details.
+ return strings::Substitute(
+ "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
+ CEscape(field->default_value_string()));
+ }
+ }
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
+ field->default_value_enum()->name();
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return name_resolver->GetClassName(field->message_type(), immutable) +
+ ".getDefaultInstance()";
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
+ // Switch on CppType since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return field->default_value_int32() == 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return field->default_value_uint32() == 0;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return field->default_value_int64() == 0L;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return field->default_value_uint64() == 0L;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return field->default_value_double() == 0.0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return field->default_value_float() == 0.0;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() == false;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return field->default_value_enum()->number() == 0;
+ case FieldDescriptor::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return false;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) {
+ return GetJavaType(field) == JAVATYPE_BYTES &&
+ field->default_value_string() != "";
+}
+
+const char* bit_masks[] = {
+ "0x00000001", "0x00000002", "0x00000004", "0x00000008",
+ "0x00000010", "0x00000020", "0x00000040", "0x00000080",
+
+ "0x00000100", "0x00000200", "0x00000400", "0x00000800",
+ "0x00001000", "0x00002000", "0x00004000", "0x00008000",
+
+ "0x00010000", "0x00020000", "0x00040000", "0x00080000",
+ "0x00100000", "0x00200000", "0x00400000", "0x00800000",
+
+ "0x01000000", "0x02000000", "0x04000000", "0x08000000",
+ "0x10000000", "0x20000000", "0x40000000", "0x80000000",
+};
+
+std::string GetBitFieldName(int index) {
+ std::string varName = "bitField";
+ varName += StrCat(index);
+ varName += "_";
+ return varName;
+}
+
+std::string GetBitFieldNameForBit(int bitIndex) {
+ return GetBitFieldName(bitIndex / 32);
+}
+
+namespace {
+
+std::string GenerateGetBitInternal(const std::string& prefix, int bitIndex) {
+ std::string varName = prefix + GetBitFieldNameForBit(bitIndex);
+ int bitInVarIndex = bitIndex % 32;
+
+ std::string mask = bit_masks[bitInVarIndex];
+ std::string result = "((" + varName + " & " + mask + ") != 0)";
+ return result;
+}
+
+std::string GenerateSetBitInternal(const std::string& prefix, int bitIndex) {
+ std::string varName = prefix + GetBitFieldNameForBit(bitIndex);
+ int bitInVarIndex = bitIndex % 32;
+
+ std::string mask = bit_masks[bitInVarIndex];
+ std::string result = varName + " |= " + mask;
+ return result;
+}
+
+} // namespace
+
+std::string GenerateGetBit(int bitIndex) {
+ return GenerateGetBitInternal("", bitIndex);
+}
+
+std::string GenerateSetBit(int bitIndex) {
+ return GenerateSetBitInternal("", bitIndex);
+}
+
+std::string GenerateClearBit(int bitIndex) {
+ std::string varName = GetBitFieldNameForBit(bitIndex);
+ int bitInVarIndex = bitIndex % 32;
+
+ std::string mask = bit_masks[bitInVarIndex];
+ std::string result = varName + " = (" + varName + " & ~" + mask + ")";
+ return result;
+}
+
+std::string GenerateGetBitFromLocal(int bitIndex) {
+ return GenerateGetBitInternal("from_", bitIndex);
+}
+
+std::string GenerateSetBitToLocal(int bitIndex) {
+ return GenerateSetBitInternal("to_", bitIndex);
+}
+
+std::string GenerateGetBitMutableLocal(int bitIndex) {
+ return GenerateGetBitInternal("mutable_", bitIndex);
+}
+
+std::string GenerateSetBitMutableLocal(int bitIndex) {
+ return GenerateSetBitInternal("mutable_", bitIndex);
+}
+
+bool IsReferenceType(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT:
+ return false;
+ case JAVATYPE_LONG:
+ return false;
+ case JAVATYPE_FLOAT:
+ return false;
+ case JAVATYPE_DOUBLE:
+ return false;
+ case JAVATYPE_BOOLEAN:
+ return false;
+ case JAVATYPE_STRING:
+ return true;
+ case JAVATYPE_BYTES:
+ return true;
+ case JAVATYPE_ENUM:
+ return true;
+ case JAVATYPE_MESSAGE:
+ return true;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
+ switch (GetType(field)) {
+ 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;
+}
+
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32:
+ return -1;
+ case FieldDescriptor::TYPE_INT64:
+ return -1;
+ case FieldDescriptor::TYPE_UINT32:
+ return -1;
+ case FieldDescriptor::TYPE_UINT64:
+ return -1;
+ case FieldDescriptor::TYPE_SINT32:
+ return -1;
+ case FieldDescriptor::TYPE_SINT64:
+ return -1;
+ case FieldDescriptor::TYPE_FIXED32:
+ return WireFormatLite::kFixed32Size;
+ case FieldDescriptor::TYPE_FIXED64:
+ return WireFormatLite::kFixed64Size;
+ case FieldDescriptor::TYPE_SFIXED32:
+ return WireFormatLite::kSFixed32Size;
+ case FieldDescriptor::TYPE_SFIXED64:
+ return WireFormatLite::kSFixed64Size;
+ case FieldDescriptor::TYPE_FLOAT:
+ return WireFormatLite::kFloatSize;
+ case FieldDescriptor::TYPE_DOUBLE:
+ return WireFormatLite::kDoubleSize;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return WireFormatLite::kBoolSize;
+ case FieldDescriptor::TYPE_ENUM:
+ return -1;
+
+ case FieldDescriptor::TYPE_STRING:
+ return -1;
+ case FieldDescriptor::TYPE_BYTES:
+ return -1;
+ case FieldDescriptor::TYPE_GROUP:
+ return -1;
+ case FieldDescriptor::TYPE_MESSAGE:
+ return -1;
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return -1;
+}
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it. The caller should delete the returned array.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor*[descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
+ return fields;
+}
+
+// Returns true if the message type has any required fields. If it doesn't,
+// we can optimize out calls to its isInitialized() method.
+//
+// already_seen is used to avoid checking the same type multiple times
+// (and also to protect against recursion).
+bool HasRequiredFields(const Descriptor* type,
+ std::unordered_set<const Descriptor*>* already_seen) {
+ if (already_seen->count(type) > 0) {
+ // The type is already in cache. This means that either:
+ // a. The type has no required fields.
+ // b. We are in the midst of checking if the type has required fields,
+ // somewhere up the stack. In this case, we know that if the type
+ // has any required fields, they'll be found when we return to it,
+ // and the whole call to HasRequiredFields() will return true.
+ // Therefore, we don't have to check if this type has required fields
+ // here.
+ return false;
+ }
+ already_seen->insert(type);
+
+ // If the type has extensions, an extension with message type could contain
+ // required fields, so we have to be conservative and assume such an
+ // extension exists.
+ if (type->extension_range_count() > 0) return true;
+
+ for (int i = 0; i < type->field_count(); i++) {
+ const FieldDescriptor* field = type->field(i);
+ if (field->is_required()) {
+ return true;
+ }
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ if (HasRequiredFields(field->message_type(), already_seen)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool HasRequiredFields(const Descriptor* type) {
+ std::unordered_set<const Descriptor*> already_seen;
+ return HasRequiredFields(type, &already_seen);
+}
+
+bool HasRepeatedFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* field = descriptor->field(i);
+ if (field->is_repeated()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Encode an unsigned 32-bit value into a sequence of UTF-16 characters.
+//
+// If the value is in [0x0000, 0xD7FF], we encode it with a single character
+// with the same numeric value.
+//
+// If the value is larger than 0xD7FF, we encode its lowest 13 bits into a
+// character in the range [0xE000, 0xFFFF] by combining these 13 bits with
+// 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and
+// encode the remaining value by repeating this same process until we get to
+// a value in [0x0000, 0xD7FF] where we will encode it using a character with
+// the same numeric value.
+//
+// Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
+// There will be no surrogate pairs in the encoded character sequence.
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+ std::vector<uint16_t>* output) {
+ // For values in [0x0000, 0xD7FF], only use one char to encode it.
+ if (number < 0xD800) {
+ output->push_back(static_cast<uint16_t>(number));
+ return;
+ }
+ // Encode into multiple chars. All except the last char will be in the range
+ // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF].
+ // Note that we don't use any value in range [0xD800, 0xDFFF] because they
+ // have to come in pairs and the encoding is just more space-efficient w/o
+ // them.
+ while (number >= 0xD800) {
+ // [0xE000, 0xFFFF] can represent 13 bits of info.
+ output->push_back(static_cast<uint16_t>(0xE000 | (number & 0x1FFF)));
+ number >>= 13;
+ }
+ output->push_back(static_cast<uint16_t>(number));
+}
+
+int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
+ // j/c/g/protobuf/FieldType.java lists field types in a slightly different
+ // order from FieldDescriptor::Type so we can't do a simple cast.
+ //
+ // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order.
+ int result = field->type();
+ if (result == FieldDescriptor::TYPE_GROUP) {
+ return 17;
+ } else if (result < FieldDescriptor::TYPE_GROUP) {
+ return result - 1;
+ } else {
+ return result - 2;
+ }
+}
+
+int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ return 49;
+ } else {
+ return GetExperimentalJavaFieldTypeForSingular(field) + 18;
+ }
+}
+
+int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) {
+ int result = field->type();
+ if (result < FieldDescriptor::TYPE_STRING) {
+ return result + 34;
+ } else if (result > FieldDescriptor::TYPE_BYTES) {
+ return result + 30;
+ } else {
+ GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed.";
+ return 0;
+ }
+}
+
+int GetExperimentalJavaFieldType(const FieldDescriptor* field) {
+ static const int kMapFieldType = 50;
+ static const int kOneofFieldTypeOffset = 51;
+ static const int kRequiredBit = 0x100;
+ static const int kUtf8CheckBit = 0x200;
+ static const int kCheckInitialized = 0x400;
+ static const int kMapWithProto2EnumValue = 0x800;
+ static const int kHasHasBit = 0x1000;
+ int extra_bits = field->is_required() ? kRequiredBit : 0;
+ if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) {
+ extra_bits |= kUtf8CheckBit;
+ }
+ if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type()))) {
+ extra_bits |= kCheckInitialized;
+ }
+ if (HasHasbit(field)) {
+ extra_bits |= kHasHasBit;
+ }
+
+ if (field->is_map()) {
+ if (!SupportUnknownEnumValue(field)) {
+ const FieldDescriptor* value =
+ field->message_type()->FindFieldByName("value");
+ if (GetJavaType(value) == JAVATYPE_ENUM) {
+ extra_bits |= kMapWithProto2EnumValue;
+ }
+ }
+ return kMapFieldType | extra_bits;
+ } else if (field->is_packed()) {
+ return GetExperimentalJavaFieldTypeForPacked(field);
+ } else if (field->is_repeated()) {
+ return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits;
+ } else if (IsRealOneof(field)) {
+ return (GetExperimentalJavaFieldTypeForSingular(field) +
+ kOneofFieldTypeOffset) |
+ extra_bits;
+ } else {
+ return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits;
+ }
+}
+
+// Escape a UTF-16 character to be embedded in a Java string.
+void EscapeUtf16ToString(uint16_t code, std::string* output) {
+ if (code == '\t') {
+ output->append("\\t");
+ } else if (code == '\b') {
+ output->append("\\b");
+ } else if (code == '\n') {
+ output->append("\\n");
+ } else if (code == '\r') {
+ output->append("\\r");
+ } else if (code == '\f') {
+ output->append("\\f");
+ } else if (code == '\'') {
+ output->append("\\'");
+ } else if (code == '\"') {
+ output->append("\\\"");
+ } else if (code == '\\') {
+ output->append("\\\\");
+ } else if (code >= 0x20 && code <= 0x7f) {
+ output->push_back(static_cast<char>(code));
+ } else {
+ output->append(StringPrintf("\\u%04x", code));
+ }
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.h
new file mode 100644
index 00000000..428aa254
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_helpers.h
@@ -0,0 +1,459 @@
+// 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_JAVA_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
+
+#include <cstdint>
+#include <string>
+
+#include <compiler/java/java_context.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <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[];
+
+bool IsForbiddenKotlin(const std::string& field_name);
+
+// If annotation_file is non-empty, prints a javax.annotation.Generated
+// annotation to the given Printer. annotation_file will be referenced in the
+// annotation's comments field. delimiter should be the Printer's delimiter
+// character. annotation_file will be included verbatim into a Java literal
+// string, so it should not contain quotes or invalid Java escape sequences;
+// however, these are unlikely to appear in practice, as the value of
+// annotation_file should be generated from the filename of the source file
+// being annotated (which in turn must be a Java identifier plus ".java").
+void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$',
+ const std::string& annotation_file = "");
+
+// If a GeneratedMessageLite contains non-lite enums, then its verifier
+// must be instantiated inline, rather than retrieved from the enum class.
+void PrintEnumVerifierLogic(io::Printer* printer,
+ const FieldDescriptor* descriptor,
+ const std::map<std::string, std::string>& variables,
+ const char* var_name,
+ const char* terminating_string, bool enforce_lite);
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+std::string ToCamelCase(const std::string& input, bool lower_first);
+
+char ToUpperCh(char ch);
+char ToLowerCh(char ch);
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+std::string UnderscoresToCamelCase(const std::string& name,
+ bool cap_first_letter);
+// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
+// "fooBarBaz" or "FooBarBaz", respectively.
+std::string UnderscoresToCamelCase(const FieldDescriptor* field);
+std::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.)
+std::string UnderscoresToCamelCase(const MethodDescriptor* method);
+
+// Same as UnderscoresToCamelCase, but checks for reserved keywords
+std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field);
+
+// Similar to UnderscoresToCamelCase, but guarantees that the result is a
+// complete Java identifier by adding a _ if needed.
+std::string CamelCaseFieldName(const FieldDescriptor* field);
+
+// Get an identifier that uniquely identifies this type within the file.
+// This is used to declare static variables related to this type at the
+// outermost file scope.
+std::string UniqueFileScopeIdentifier(const Descriptor* descriptor);
+
+// Gets the unqualified class name for the file. For each .proto file, there
+// will be one Java class containing all the immutable messages and another
+// Java class containing all the mutable messages.
+// TODO(xiaofeng): remove the default value after updating client code.
+std::string FileClassName(const FileDescriptor* file, bool immutable = true);
+
+// Returns the file's Java package name.
+std::string FileJavaPackage(const FileDescriptor* file, bool immutable);
+
+// Returns output directory for the given package name.
+std::string JavaPackageToDir(std::string package_name);
+
+// Comma-separate list of option-specified interfaces implemented by the
+// Message, to follow the "implements" declaration of the Message definition.
+std::string ExtraMessageInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces implemented by the
+// MutableMessage, to follow the "implements" declaration of the MutableMessage
+// definition.
+std::string ExtraMutableMessageInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces implemented by the
+// Builder, to follow the "implements" declaration of the Builder definition.
+std::string ExtraBuilderInterfaces(const Descriptor* descriptor);
+// Comma-separate list of option-specified interfaces extended by the
+// MessageOrBuilder, to follow the "extends" declaration of the
+// MessageOrBuilder definition.
+std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor);
+
+// Get the unqualified Java class name for mutable messages. i.e. without
+// package or outer classnames.
+inline std::string ShortMutableJavaClassName(const Descriptor* descriptor) {
+ return descriptor->name();
+}
+
+// Whether the given descriptor is for one of the core descriptor protos. We
+// cannot currently use the new runtime with core protos since there is a
+// bootstrapping problem with obtaining their descriptors.
+inline bool IsDescriptorProto(const Descriptor* descriptor) {
+ return descriptor->file()->name() == "net/proto2/proto/descriptor.proto" ||
+ descriptor->file()->name() == "google/protobuf/descriptor.proto";
+}
+
+// Returns the stored type string used by the experimental runtime for oneof
+// fields.
+std::string GetOneofStoredType(const FieldDescriptor* field);
+
+
+// Whether we should generate multiple java files for messages.
+inline bool MultipleJavaFiles(const FileDescriptor* descriptor,
+ bool immutable) {
+ (void)immutable;
+ return descriptor->options().java_multiple_files();
+}
+
+
+// Returns true if `descriptor` will be written to its own .java file.
+// `immutable` should be set to true if we're generating for the immutable API.
+template <typename Descriptor>
+bool IsOwnFile(const Descriptor* descriptor, bool immutable) {
+ return descriptor->containing_type() == NULL &&
+ MultipleJavaFiles(descriptor->file(), immutable);
+}
+
+template <>
+inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) {
+ return MultipleJavaFiles(descriptor->file(), immutable);
+}
+
+// If `descriptor` describes an object with its own .java file,
+// returns the name (relative to that .java file) of the file that stores
+// annotation data for that descriptor. `suffix` is usually empty, but may
+// (e.g.) be "OrBuilder" for some generated interfaces.
+template <typename Descriptor>
+std::string AnnotationFileName(const Descriptor* descriptor,
+ const std::string& suffix) {
+ return descriptor->name() + suffix + ".java.pb.meta";
+}
+
+template <typename Descriptor>
+void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer,
+ Descriptor* descriptor, bool immutable,
+ const std::string& suffix = "") {
+ if (IsOwnFile(descriptor, immutable)) {
+ PrintGeneratedAnnotation(printer, '$',
+ context->options().annotate_code
+ ? AnnotationFileName(descriptor, suffix)
+ : "");
+ }
+}
+
+// Get the unqualified name that should be used for a field's field
+// number constant.
+std::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 compatibility 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);
+
+const char* PrimitiveTypeName(JavaType type);
+
+// 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);
+
+// Kotlin source does not distinguish between primitives and non-primitives,
+// but does use Kotlin-specific qualified types for them.
+const char* KotlinTypeName(JavaType type);
+
+// Get the name of the java enum constant representing this type. E.g.,
+// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full
+// name is "com.google.protobuf.WireFormat.FieldType.INT32".
+const char* FieldTypeName(const FieldDescriptor::Type field_type);
+
+class ClassNameResolver;
+std::string DefaultValue(const FieldDescriptor* field, bool immutable,
+ ClassNameResolver* name_resolver);
+inline std::string ImmutableDefaultValue(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver) {
+ return DefaultValue(field, true, name_resolver);
+}
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
+bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field);
+
+// Does this message class have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const Descriptor* /* descriptor */,
+ bool enforce_lite) {
+ return !enforce_lite;
+}
+inline bool HasDescriptorMethods(const EnumDescriptor* /* descriptor */,
+ bool enforce_lite) {
+ return !enforce_lite;
+}
+inline bool HasDescriptorMethods(const FileDescriptor* /* descriptor */,
+ bool enforce_lite) {
+ return !enforce_lite;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor* file, bool enforce_lite) {
+ return file->service_count() > 0 &&
+ HasDescriptorMethods(file, enforce_lite) &&
+ file->options().java_generic_services();
+}
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given index.
+std::string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bitIndex / 32)
+std::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)"
+std::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)"
+std::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)"
+std::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)"
+std::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)"
+std::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)"
+std::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)"
+std::string GenerateSetBitMutableLocal(int bitIndex);
+
+// Returns whether the JavaType is a reference type.
+bool IsReferenceType(JavaType type);
+
+// Returns the capitalized name for calling relative functions in
+// CodedInputStream
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable);
+
+// For encodings with fixed sizes, returns that size in bytes. Otherwise
+// returns -1.
+int FixedSize(FieldDescriptor::Type type);
+
+// Comparators used to sort fields in MessageGenerator
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+struct ExtensionRangeOrdering {
+ bool operator()(const Descriptor::ExtensionRange* a,
+ const Descriptor::ExtensionRange* b) const {
+ return a->start < b->start;
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it. The caller should delete the returned array.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
+
+// Does this message class have any packed fields?
+inline bool HasPackedFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_packed()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Check a message type and its sub-message types recursively to see if any of
+// them has a required field. Return true if a required field is found.
+bool HasRequiredFields(const Descriptor* descriptor);
+
+inline bool IsProto2(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
+inline bool IsRealOneof(const FieldDescriptor* descriptor) {
+ return descriptor->containing_oneof() &&
+ !descriptor->containing_oneof()->is_synthetic();
+}
+
+inline bool HasHazzer(const FieldDescriptor* descriptor) {
+ return !descriptor->is_repeated() &&
+ (descriptor->message_type() || descriptor->has_optional_keyword() ||
+ IsProto2(descriptor->file()) || IsRealOneof(descriptor));
+}
+
+inline bool HasHasbit(const FieldDescriptor* descriptor) {
+ // Note that currently message fields inside oneofs have hasbits. This is
+ // surprising, as the oneof case should avoid any need for a hasbit. But if
+ // you change this method to remove hasbits for oneofs, a few tests fail.
+ // TODO(b/124347790): remove hasbits for oneofs
+ return !descriptor->is_repeated() &&
+ (descriptor->has_optional_keyword() || IsProto2(descriptor->file()));
+}
+
+// Whether generate classes expose public PARSER instances.
+inline bool ExposePublicParser(const FileDescriptor* descriptor) {
+ // TODO(liujisi): Mark the PARSER private in 3.1.x releases.
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
+// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
+// but in the message and can be queried using additional getters that return
+// ints.
+inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool SupportUnknownEnumValue(const FieldDescriptor* field) {
+ return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Check whether a message has repeated fields.
+bool HasRepeatedFields(const Descriptor* descriptor);
+
+inline bool IsMapEntry(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+inline bool IsMapField(const FieldDescriptor* descriptor) {
+ return descriptor->is_map();
+}
+
+inline bool IsAnyMessage(const Descriptor* descriptor) {
+ return descriptor->full_name() == "google.protobuf.Any";
+}
+
+inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) {
+ return descriptor->name() == "google/protobuf/wrappers.proto";
+}
+
+inline bool CheckUtf8(const FieldDescriptor* descriptor) {
+ return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
+ descriptor->file()->options().java_string_check_utf8();
+}
+
+inline std::string GeneratedCodeVersionSuffix() {
+ return "V3";
+}
+
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+ std::vector<uint16_t>* output);
+
+inline void WriteIntToUtf16CharSequence(int value,
+ std::vector<uint16_t>* output) {
+ WriteUInt32ToUtf16CharSequence(static_cast<uint32_t>(value), output);
+}
+
+// Escape a UTF-16 character so it can be embedded in a Java string literal.
+void EscapeUtf16ToString(uint16_t code, std::string* output);
+
+// Only the lowest two bytes of the return value are used. The lowest byte
+// is the integer value of a j/c/g/protobuf/FieldType enum. For the other
+// byte:
+// bit 0: whether the field is required.
+// bit 1: whether the field requires UTF-8 validation.
+// bit 2: whether the field needs isInitialized check.
+// bit 3: whether the field is a map field with proto2 enum value.
+// bits 4-7: unused
+int GetExperimentalJavaFieldType(const FieldDescriptor* field);
+
+// To get the total number of entries need to be built for experimental runtime
+// and the first field number that are not in the table part
+std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber(
+ const FieldDescriptor** fields, int count);
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.cc
new file mode 100644
index 00000000..d043ed80
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.cc
@@ -0,0 +1,162 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <compiler/java/java_kotlin_generator.h>
+
+#include <compiler/java/java_file.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_options.h>
+#include <compiler/java/java_generator.h>
+#include <compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+KotlinGenerator::KotlinGenerator() {}
+KotlinGenerator::~KotlinGenerator() {}
+
+uint64_t KotlinGenerator::GetSupportedFeatures() const {
+ return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
+bool KotlinGenerator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* context,
+ std::string* error) const {
+ // -----------------------------------------------------------------
+ // parse generator options
+
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+ Options file_options;
+
+ for (auto& option : options) {
+ if (option.first == "output_list_file") {
+ file_options.output_list_file = option.second;
+ } else if (option.first == "immutable") {
+ file_options.generate_immutable_code = true;
+ } else if (option.first == "mutable") {
+ *error = "Mutable not supported by Kotlin generator";
+ return false;
+ } else if (option.first == "shared") {
+ file_options.generate_shared_code = true;
+ } else if (option.first == "lite") {
+ file_options.enforce_lite = true;
+ } else if (option.first == "annotate_code") {
+ file_options.annotate_code = true;
+ } else if (option.first == "annotation_list_file") {
+ file_options.annotation_list_file = option.second;
+ } else {
+ *error = "Unknown generator option: " + option.first;
+ return false;
+ }
+ }
+
+ // By default we generate immutable code and shared code for immutable API.
+ if (!file_options.generate_immutable_code &&
+ !file_options.generate_shared_code) {
+ file_options.generate_immutable_code = true;
+ file_options.generate_shared_code = true;
+ }
+
+ std::vector<std::string> all_files;
+ std::vector<std::string> all_annotations;
+
+ std::unique_ptr<FileGenerator> file_generator;
+ if (file_options.generate_immutable_code) {
+ file_generator.reset(
+ new FileGenerator(file, file_options, /* immutable_api = */ true));
+ }
+
+ if (!file_generator->Validate(error)) {
+ return false;
+ }
+
+ auto open_file = [context](const std::string& filename) {
+ return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
+ };
+ std::string package_dir = JavaPackageToDir(file_generator->java_package());
+ std::string kotlin_filename = package_dir;
+ kotlin_filename += file_generator->GetKotlinClassname();
+ kotlin_filename += ".kt";
+ all_files.push_back(kotlin_filename);
+ std::string info_full_path = kotlin_filename + ".pb.meta";
+ if (file_options.annotate_code) {
+ all_annotations.push_back(info_full_path);
+ }
+
+ // Generate main kotlin file.
+ auto output = open_file(kotlin_filename);
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ file_options.annotate_code ? &annotation_collector : nullptr);
+
+ file_generator->GenerateKotlinSiblings(package_dir, context, &all_files,
+ &all_annotations);
+
+ if (file_options.annotate_code) {
+ auto info_output = open_file(info_full_path);
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
+
+ // Generate output list if requested.
+ if (!file_options.output_list_file.empty()) {
+ // Generate output list. This is just a simple text file placed in a
+ // deterministic location which lists the .kt files being generated.
+ auto srclist_raw_output = open_file(file_options.output_list_file);
+ io::Printer srclist_printer(srclist_raw_output.get(), '$');
+ for (auto& all_file : all_files) {
+ srclist_printer.Print("$filename$\n", "filename", all_file);
+ }
+ }
+
+ if (!file_options.annotation_list_file.empty()) {
+ // Generate output list. This is just a simple text file placed in a
+ // deterministic location which lists the .kt files being generated.
+ auto annotation_list_raw_output =
+ open_file(file_options.annotation_list_file);
+ io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
+ for (auto& all_annotation : all_annotations) {
+ annotation_list_printer.Print("$filename$\n", "filename", all_annotation);
+ }
+ }
+
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.h
new file mode 100644
index 00000000..87ae2507
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_kotlin_generator.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates Kotlin code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// CodeGenerator implementation which generates Kotlin code. If you create your
+// own protocol compiler binary and you want it to support Kotlin output, you
+// can do so by registering an instance of this CodeGenerator with the
+// CommandLineInterface in your main() function.
+class PROTOC_EXPORT KotlinGenerator : public CodeGenerator {
+ public:
+ KotlinGenerator();
+ ~KotlinGenerator() override;
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(KotlinGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.cc
new file mode 100644
index 00000000..602e5954
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.cc
@@ -0,0 +1,876 @@
+// 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 <compiler/java/java_map_field.h>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+std::string TypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver, bool boxed) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+ : PrimitiveTypeName(GetJavaType(field));
+ }
+}
+
+std::string KotlinTypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return KotlinTypeName(GetJavaType(field));
+ }
+}
+
+std::string WireType(const FieldDescriptor* field) {
+ return "com.google.protobuf.WireFormat.FieldType." +
+ std::string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ Context* context,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+ ClassNameResolver* name_resolver = context->GetNameResolver();
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ const JavaType keyJavaType = GetJavaType(key);
+ const JavaType valueJavaType = GetJavaType(value);
+
+ (*variables)["key_type"] = TypeName(key, name_resolver, false);
+ std::string boxed_key_type = TypeName(key, name_resolver, true);
+ (*variables)["boxed_key_type"] = boxed_key_type;
+ (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
+ (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
+ // Used for calling the serialization function.
+ (*variables)["short_key_type"] =
+ boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
+ (*variables)["key_wire_type"] = WireType(key);
+ (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+ (*variables)["key_null_check"] =
+ IsReferenceType(keyJavaType)
+ ? "if (key == null) { throw new NullPointerException(\"map key\"); }"
+ : "";
+ (*variables)["value_null_check"] =
+ valueJavaType != JAVATYPE_ENUM && IsReferenceType(valueJavaType)
+ ? "if (value == null) {\n"
+ " throw new NullPointerException(\"map value\");\n"
+ "}\n"
+ : "";
+ if (valueJavaType == JAVATYPE_ENUM) {
+ // We store enums as Integers internally.
+ (*variables)["value_type"] = "int";
+ (*variables)["boxed_value_type"] = "java.lang.Integer";
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+ (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ // Map unknown values to a special UNRECOGNIZED value if supported.
+ (*variables)["unrecognized_value"] =
+ (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+ } else {
+ // Map unknown values to the default value if we don't have UNRECOGNIZED.
+ (*variables)["unrecognized_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ } else {
+ (*variables)["value_type"] = TypeName(value, name_resolver, false);
+ (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["on_changed"] = "onChanged();";
+
+ // 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)["default_entry"] =
+ (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
+ (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+ (*variables)["descriptor"] =
+ name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" +
+ UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, ";
+ (*variables)["ver"] = GeneratedCodeVersionSuffix();
+}
+
+} // namespace
+
+ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor), context,
+ &variables_);
+}
+
+ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {}
+
+int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; }
+
+int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; }
+
+void ImmutableMapFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$Map$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$Value$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$ValueMap$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$Map$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntry<\n"
+ " $type_parameters$> defaultEntry =\n"
+ " com.google.protobuf.MapEntry\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $descriptor$\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n"
+ "}\n");
+ printer->Print(variables_,
+ "private com.google.protobuf.MapField<\n"
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "private static final\n"
+ "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+ " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+ " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+ " $value_enum_type$.internalGetValueMap(),\n"
+ " $unrecognized_value$);\n");
+ printer->Print(
+ variables_,
+ "private static final java.util.Map<$boxed_key_type$, "
+ "$value_enum_type$>\n"
+ "internalGetAdapted$capitalized_name$Map(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map) {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " map, $name$ValueConverter);\n"
+ "}\n");
+ }
+ GenerateMapGetters(printer);
+}
+
+void ImmutableMapFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.MapField<\n"
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapField<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " $on_changed$;\n"
+ " if ($name$_ == null) {\n"
+ " $name$_ = com.google.protobuf.MapField.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
+ GenerateMapGetters(printer);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public Builder ${$clear$capitalized_name$$}$() {\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .clear();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public Builder ${$remove$capitalized_name$$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .remove(key);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use alternate mutation accessors instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$getMutable$capitalized_name$$}$() {\n"
+ " return internalGetAdapted$capitalized_name$Map(\n"
+ " internalGetMutable$capitalized_name$().getMutableMap());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ value) {\n"
+ " $key_null_check$\n"
+ " $value_null_check$\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .put(key, $name$ValueConverter.doBackward(value));\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " internalGetAdapted$capitalized_name$Map(\n"
+ " internalGetMutable$capitalized_name$().getMutableMap())\n"
+ " .putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use alternate mutation accessors instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$getMutable$capitalized_name$Value$}$() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ value) {\n"
+ " $key_null_check$\n"
+ " $value_null_check$\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .put(key, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use alternate mutation accessors instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$type_parameters$>\n"
+ "${$getMutable$capitalized_name$$}$() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$"
+ "public Builder ${$put$capitalized_name$$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ value) {\n"
+ " $key_null_check$\n"
+ " $value_null_check$\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .put(key, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public Builder ${$putAll$capitalized_name$$}$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " internalGetMutable$capitalized_name$().getMutableMap()\n"
+ " .putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMapFieldGenerator::GenerateMapGetters(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public int ${$get$capitalized_name$Count$}$() {\n"
+ " return internalGet$capitalized_name$().getMap().size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "@java.lang.Override\n"
+ "public boolean ${$contains$capitalized_name$$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " return internalGet$capitalized_name$().getMap().containsKey(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return internalGetAdapted$capitalized_name$Map(\n"
+ " internalGet$capitalized_name$().getMap());"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " return map.containsKey(key)\n"
+ " ? $name$ValueConverter.doForward(map.get(key))\n"
+ " : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return $name$ValueConverter.doForward(map.get(key));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$Value$}$() {\n"
+ " return get$capitalized_name$ValueMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$ValueMap$}$() {\n"
+ " return internalGet$capitalized_name$().getMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return internalGet$capitalized_name$().getMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " internalGet$capitalized_name$().getMap();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMapFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @JvmName(\"get$kt_capitalized_name$Map\")\n"
+ " get() = com.google.protobuf.kotlin.DslMap(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
+ " )\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@JvmName(\"put$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
+ " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"set$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
+ " put(key, value)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"remove$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .remove(key: $kt_key_type$) {\n"
+ " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"putAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
+ "{\n"
+ " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ " }\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "internalGetMutable$capitalized_name$().clear();\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ " other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "result.$name$_ = internalGet$capitalized_name$();\n"
+ "result.$name$_.makeImmutable();\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = com.google.protobuf.MapField.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
+ if (!SupportUnknownEnumValue(descriptor_->file()) &&
+ GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+ "com.google.protobuf.MapEntry<$type_parameters$>\n"
+ "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+ printer->Print(
+ variables_,
+ "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
+ " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+ "} else {\n"
+ " $name$_.getMutableMap().put(\n"
+ " $name$__.getKey(), $name$__.getValue());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.MapEntry<$type_parameters$>\n"
+ "$name$__ = input.readMessage(\n"
+ " $default_entry$.getParserForType(), extensionRegistry);\n"
+ "$name$_.getMutableMap().put(\n"
+ " $name$__.getKey(), $name$__.getValue());\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ // Nothing to do here.
+}
+
+void ImmutableMapFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .serialize$short_key_type$MapTo(\n"
+ " output,\n"
+ " internalGet$capitalized_name$(),\n"
+ " $default_entry$,\n"
+ " $number$);\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry<$type_parameters$>\n"
+ " $name$__ = $default_entry$.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeMessageSize($number$, $name$__);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!internalGet$capitalized_name$().equals(\n"
+ " other.internalGet$capitalized_name$())) return false;\n");
+}
+
+void ImmutableMapFieldGenerator::GenerateHashCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
+ "}\n");
+}
+
+std::string ImmutableMapFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.h
new file mode 100644
index 00000000..e309391f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ Context* context);
+ ~ImmutableMapFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+ void GenerateMapGetters(io::Printer* printer) const;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.cc
new file mode 100644
index 00000000..b210bc45
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.cc
@@ -0,0 +1,909 @@
+// 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 <compiler/java/java_map_field_lite.h>
+
+#include <cstdint>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+std::string TypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver, bool boxed) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+ : PrimitiveTypeName(GetJavaType(field));
+ }
+}
+
+std::string KotlinTypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return KotlinTypeName(GetJavaType(field));
+ }
+}
+
+std::string WireType(const FieldDescriptor* field) {
+ return "com.google.protobuf.WireFormat.FieldType." +
+ std::string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ Context* context,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ ClassNameResolver* name_resolver = context->GetNameResolver();
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ const JavaType keyJavaType = GetJavaType(key);
+ const JavaType valueJavaType = GetJavaType(value);
+
+ (*variables)["key_type"] = TypeName(key, name_resolver, false);
+ (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+ (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
+ (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
+ (*variables)["key_wire_type"] = WireType(key);
+ (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+ // We use `x.getClass()` as a null check because it generates less bytecode
+ // than an `if (x == null) { throw ... }` statement.
+ (*variables)["key_null_check"] =
+ IsReferenceType(keyJavaType)
+ ? "java.lang.Class<?> keyClass = key.getClass();"
+ : "";
+ (*variables)["value_null_check"] =
+ IsReferenceType(valueJavaType)
+ ? "java.lang.Class<?> valueClass = value.getClass();"
+ : "";
+
+ if (GetJavaType(value) == JAVATYPE_ENUM) {
+ // We store enums as Integers internally.
+ (*variables)["value_type"] = "int";
+ (*variables)["boxed_value_type"] = "java.lang.Integer";
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+ (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ // Map unknown values to a special UNRECOGNIZED value if supported.
+ (*variables)["unrecognized_value"] =
+ (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+ } else {
+ // Map unknown values to the default value if we don't have UNRECOGNIZED.
+ (*variables)["unrecognized_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ } else {
+ (*variables)["value_type"] = TypeName(value, name_resolver, false);
+ (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+
+ (*variables)["default_entry"] =
+ (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
+}
+
+} // namespace
+
+ImmutableMapFieldLiteGenerator::ImmutableMapFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : descriptor_(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor), context,
+ &variables_);
+}
+
+ImmutableMapFieldLiteGenerator::~ImmutableMapFieldLiteGenerator() {}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { return 0; }
+
+void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$Map$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$Value$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$ValueMap$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "${$get$capitalized_name$Map$}$();\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue);\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key);\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntryLite<\n"
+ " $type_parameters$> defaultEntry =\n"
+ " com.google.protobuf.MapEntryLite\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n"
+ "}\n");
+ printer->Print(variables_,
+ "private com.google.protobuf.MapFieldLite<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapFieldLite.emptyMapField();\n"
+ "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.mutableCopy();\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public int ${$get$capitalized_name$Count$}$() {\n"
+ " return internalGet$capitalized_name$().size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public boolean ${$contains$capitalized_name$$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " return internalGet$capitalized_name$().containsKey(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "private static final\n"
+ "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+ " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+ " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+ " $value_enum_type$.internalGetValueMap(),\n"
+ " $unrecognized_value$);\n");
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " internalGet$capitalized_name$(),\n"
+ " $name$ValueConverter));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " return map.containsKey(key)\n"
+ " ? $name$ValueConverter.doForward(map.get(key))\n"
+ " : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return $name$ValueConverter.doForward(map.get(key));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$Value$}$() {\n"
+ " return get$capitalized_name$ValueMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$ValueMap$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " internalGet$capitalized_name$());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " internalGet$capitalized_name$());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " internalGet$capitalized_name$();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ // Generate private setters for the builder to proxy into.
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$Map() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " internalGetMutable$capitalized_name$(),\n"
+ " $name$ValueConverter);\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$ValueMap() {\n"
+ " return internalGetMutable$capitalized_name$();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$Map() {\n"
+ " return internalGetMutable$capitalized_name$();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ printer->Print(variables_,
+ "\"$name$_\",\n"
+ "$default_entry$,\n");
+ if (!SupportUnknownEnumValue(descriptor_) &&
+ GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ PrintEnumVerifierLogic(printer, ValueField(descriptor_), variables_,
+ /*var_name=*/"$value_enum_type$",
+ /*terminating_string=*/",\n",
+ /*enforce_lite=*/context_->EnforceLite());
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public int ${$get$capitalized_name$Count$}$() {\n"
+ " return instance.get$capitalized_name$Map().size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public boolean ${$contains$capitalized_name$$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " return instance.get$capitalized_name$Map().containsKey(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().clear();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$\n"
+ "public Builder ${$remove$capitalized_name$$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().remove(key);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " instance.get$capitalized_name$Map());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
+ " instance.get$capitalized_name$Map();\n"
+ " return map.containsKey(key)\n"
+ " ? map.get(key)\n"
+ " : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
+ " instance.get$capitalized_name$Map();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
+ " $key_type$ key,\n"
+ " $value_enum_type$ value) {\n"
+ " $key_null_check$\n"
+ " $value_null_check$\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().put(key, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$Value$}$() {\n"
+ " return get$capitalized_name$ValueMap();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "${$get$capitalized_name$ValueMap$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " instance.get$capitalized_name$ValueMap());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " instance.get$capitalized_name$ValueMap();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+ " instance.get$capitalized_name$ValueMap();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ value) {\n"
+ " $key_null_check$\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+ } else {
+ printer->Print(variables_,
+ "/**\n"
+ " * Use {@link #get$capitalized_name$Map()} instead.\n"
+ " */\n"
+ "@java.lang.Override\n"
+ "@java.lang.Deprecated\n"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$$}$() {\n"
+ " return get$capitalized_name$Map();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$"
+ "public java.util.Map<$type_parameters$> "
+ "${$get$capitalized_name$Map$}$() {\n"
+ " return java.util.Collections.unmodifiableMap(\n"
+ " instance.get$capitalized_name$Map());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ defaultValue) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " instance.get$capitalized_name$Map();\n"
+ " return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$\n"
+ "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+ " $key_type$ key) {\n"
+ " $key_null_check$\n"
+ " java.util.Map<$type_parameters$> map =\n"
+ " instance.get$capitalized_name$Map();\n"
+ " if (!map.containsKey(key)) {\n"
+ " throw new java.lang.IllegalArgumentException();\n"
+ " }\n"
+ " return map.get(key);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$"
+ "public Builder ${$put$capitalized_name$$}$(\n"
+ " $key_type$ key,\n"
+ " $value_type$ value) {\n"
+ " $key_null_check$\n"
+ " $value_null_check$\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().put(key, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$"
+ "public Builder ${$putAll$capitalized_name$$}$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.getMutable$capitalized_name$Map().putAll(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @JvmName(\"get$kt_capitalized_name$Map\")\n"
+ " get() = com.google.protobuf.kotlin.DslMap(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
+ " )\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@JvmName(\"put$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
+ " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"set$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
+ " put(key, value)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"remove$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .remove(key: $kt_key_type$) {\n"
+ " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"putAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
+ "{\n"
+ " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
+ " }\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslMap"
+ "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " .clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ " }\n");
+}
+
+void ImmutableMapFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+std::string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.h
new file mode 100644
index 00000000..7017982d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_map_field_lite.h
@@ -0,0 +1,74 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+
+#include <cstdint>
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutableMapFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.cc
new file mode 100644
index 00000000..38edc769
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.cc
@@ -0,0 +1,1729 @@
+// 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 <compiler/java/java_message.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum.h>
+#include <compiler/java/java_extension.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_message_builder.h>
+#include <compiler/java/java_message_builder_lite.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+std::string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+// ===================================================================
+
+MessageGenerator::MessageGenerator(const Descriptor* descriptor)
+ : descriptor_(descriptor) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (IsRealOneof(descriptor_->field(i))) {
+ oneofs_.insert(descriptor_->field(i)->containing_oneof());
+ }
+ }
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+// ===================================================================
+ImmutableMessageGenerator::ImmutableMessageGenerator(
+ const Descriptor* descriptor, Context* context)
+ : MessageGenerator(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A non-lite message generator is used to "
+ "generate lite messages.";
+}
+
+ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
+
+void ImmutableMessageGenerator::GenerateStaticVariables(
+ io::Printer* printer, int* bytecode_estimate) {
+ // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
+ // used in the construction of descriptors, we have a tricky bootstrapping
+ // problem. To help control static initialization order, we make sure all
+ // descriptors and other static data that depends on them are members of
+ // the outermost class in the file. This way, they will be initialized in
+ // a deterministic order.
+
+ std::map<std::string, std::string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = StrCat(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
+ }
+ if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+ // We can only make these package-private since the classes that use them
+ // are in separate files.
+ vars["private"] = "";
+ } else {
+ vars["private"] = "private ";
+ }
+ if (*bytecode_estimate <= kMaxStaticSize) {
+ vars["final"] = "final ";
+ } else {
+ vars["final"] = "";
+ }
+
+ // The descriptor for this type.
+ printer->Print(
+ vars,
+ // TODO(teboring): final needs to be added back. The way to fix it is to
+ // generate methods that can construct the types, and then still declare
+ // the types, and then init them in clinit with the new method calls.
+ "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
+ " internal_$identifier$_descriptor;\n");
+ *bytecode_estimate += 30;
+
+ // And the FieldAccessorTable.
+ GenerateFieldAccessorTable(printer, bytecode_estimate);
+
+ // Generate static members for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariables(printer, bytecode_estimate);
+ }
+}
+
+int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
+ io::Printer* printer) {
+ int bytecode_estimate = 0;
+ std::map<std::string, std::string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = StrCat(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
+ }
+
+ // The descriptor for this type.
+ if (descriptor_->containing_type() == NULL) {
+ printer->Print(vars,
+ "internal_$identifier$_descriptor =\n"
+ " getDescriptor().getMessageTypes().get($index$);\n");
+ bytecode_estimate += 30;
+ } else {
+ printer->Print(
+ vars,
+ "internal_$identifier$_descriptor =\n"
+ " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+ bytecode_estimate += 30;
+ }
+
+ // And the FieldAccessorTable.
+ bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
+
+ // Generate static member initializers for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ bytecode_estimate +=
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
+ }
+ return bytecode_estimate;
+}
+
+void ImmutableMessageGenerator::GenerateFieldAccessorTable(
+ io::Printer* printer, int* bytecode_estimate) {
+ std::map<std::string, std::string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+ // We can only make these package-private since the classes that use them
+ // are in separate files.
+ vars["private"] = "";
+ } else {
+ vars["private"] = "private ";
+ }
+ if (*bytecode_estimate <= kMaxStaticSize) {
+ vars["final"] = "final ";
+ } else {
+ vars["final"] = "";
+ }
+ vars["ver"] = GeneratedCodeVersionSuffix();
+ printer->Print(
+ vars,
+ "$private$static $final$\n"
+ " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
+ " internal_$identifier$_fieldAccessorTable;\n");
+
+ // The following bytecode_estimate calculation logic must stay in sync with
+ // the similar logic in the GenerateFieldAccessorTableInitializer method below
+ // to make sure that the generated static final fields are initialized in the
+ // static initialization block directly.
+ //
+ // 6 bytes per field and oneof
+ *bytecode_estimate +=
+ 10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count();
+}
+
+int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
+ io::Printer* printer) {
+ int bytecode_estimate = 10;
+ printer->Print(
+ "internal_$identifier$_fieldAccessorTable = new\n"
+ " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
+ " internal_$identifier$_descriptor,\n"
+ " new java.lang.String[] { ",
+ "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+ // All the bytecode_estimate calculation logic in this method must stay in
+ // sync with the similar logic in the GenerateFieldAccessorTable method
+ // above. See the corresponding comment in GenerateFieldAccessorTable for
+ // details.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bytecode_estimate += 6;
+ printer->Print("\"$field_name$\", ", "field_name", info->capitalized_name);
+ }
+ // We reproduce synthetic oneofs here since proto reflection needs these.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
+ bytecode_estimate += 6;
+ printer->Print("\"$oneof_name$\", ", "oneof_name", info->capitalized_name);
+ }
+ printer->Print("});\n");
+ return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+ /* immutable = */ true, "OrBuilder");
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessage$ver$.\n"
+ " ExtendableMessageOrBuilder<$classname$> {\n",
+ "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name(), "{", "", "}", "", "ver",
+ GeneratedCodeVersionSuffix());
+ } else {
+ printer->Print(
+ "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageOrBuilder {\n",
+ "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name(), "{", "", "}", "");
+ }
+ printer->Annotate("{", "}", descriptor_);
+
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInterfaceMembers(printer);
+ }
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
+ context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+ }
+ printer->Outdent();
+
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::Generate(io::Printer* printer) {
+ bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
+
+ std::map<std::string, std::string> variables;
+ variables["static"] = is_own_file ? "" : "static ";
+ variables["classname"] = descriptor_->name();
+ variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+ variables["ver"] = GeneratedCodeVersionSuffix();
+ variables["deprecation"] =
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
+
+ WriteMessageDocComment(printer, descriptor_);
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+ /* immutable = */ true);
+ // The builder_type stores the super type name of the nested Builder class.
+ std::string builder_type;
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ variables,
+ "$deprecation$public $static$final class $classname$ extends\n");
+ printer->Annotate("classname", descriptor_);
+ printer->Print(
+ variables,
+ " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
+ " $classname$> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_),
+ GeneratedCodeVersionSuffix());
+ } else {
+ printer->Print(
+ variables,
+ "$deprecation$public $static$final class $classname$ extends\n");
+ printer->Annotate("classname", descriptor_);
+ printer->Print(variables,
+ " com.google.protobuf.GeneratedMessage$ver$ implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type =
+ strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
+ GeneratedCodeVersionSuffix());
+ }
+ printer->Print("private static final long serialVersionUID = 0L;\n");
+
+ printer->Indent();
+ // Using builder_type, instead of Builder, prevents the Builder class from
+ // being loaded into PermGen space when the default instance is created.
+ // This optimizes the PermGen space usage for clients that do not modify
+ // messages.
+ printer->Print(
+ "// Use $classname$.newBuilder() to construct.\n"
+ "private $classname$($buildertype$ builder) {\n"
+ " super(builder);\n"
+ "}\n",
+ "classname", descriptor_->name(), "buildertype", builder_type);
+ printer->Print("private $classname$() {\n", "classname", descriptor_->name());
+ printer->Indent();
+ GenerateInitializers(printer);
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ printer->Print(variables,
+ "@java.lang.Override\n"
+ "@SuppressWarnings({\"unused\"})\n"
+ "protected java.lang.Object newInstance(\n"
+ " UnusedPrivateParameter unused) {\n"
+ " return new $classname$();\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ "getUnknownFields() {\n"
+ " return this.unknownFields;\n"
+ "}\n");
+
+ if (context_->HasGeneratedMethods(descriptor_)) {
+ GenerateParsingConstructor(printer);
+ }
+
+ GenerateDescriptorMethods(printer);
+
+ // Nested types
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator(descriptor_->enum_type(i), true, context_).Generate(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate Java classes for map entry messages.
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i),
+ context_);
+ messageGenerator.GenerateInterface(printer);
+ messageGenerator.Generate(printer);
+ }
+
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits +=
+ field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+
+ // oneof
+ std::map<std::string, std::string> vars;
+ for (auto oneof : oneofs_) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
+ vars["oneof_capitalized_name"] =
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
+ vars["oneof_index"] = StrCat((oneof)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // OneofCase enum
+ printer->Print(
+ vars,
+ "public enum $oneof_capitalized_name$Case\n"
+ // TODO(dweis): Remove EnumLite when we want to break compatibility with
+ // 3.x users
+ " implements com.google.protobuf.Internal.EnumLite,\n"
+ " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
+ printer->Indent();
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print(
+ "$deprecation$$field_name$($field_number$),\n", "deprecation",
+ field->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "field_name", ToUpper(field->name()), "field_number",
+ StrCat(field->number()));
+ }
+ printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
+ ToUpper(vars["oneof_name"]));
+ printer->Print(vars,
+ "private final int value;\n"
+ "private $oneof_capitalized_name$Case(int value) {\n"
+ " this.value = value;\n"
+ "}\n");
+ printer->Print(
+ vars,
+ "/**\n"
+ " * @param value The number of the enum to look for.\n"
+ " * @return The enum associated with the given number.\n"
+ " * @deprecated Use {@link #forNumber(int)} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+ " return forNumber(value);\n"
+ "}\n"
+ "\n"
+ "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
+ " switch (value) {\n");
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print(" case $field_number$: return $field_name$;\n",
+ "field_number", StrCat(field->number()),
+ "field_name", ToUpper(field->name()));
+ }
+ printer->Print(
+ " case 0: return $cap_oneof_name$_NOT_SET;\n"
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ "public int getNumber() {\n"
+ " return this.value;\n"
+ "}\n",
+ "cap_oneof_name", ToUpper(vars["oneof_name"]));
+ printer->Outdent();
+ printer->Print("};\n\n");
+ // oneofCase()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ "get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n");
+ }
+
+ if (IsAnyMessage(descriptor_)) {
+ GenerateAnyMethods(printer);
+ }
+
+ // Fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("public static final int $constant_name$ = $number$;\n",
+ "constant_name", FieldConstantName(descriptor_->field(i)),
+ "number", StrCat(descriptor_->field(i)->number()));
+ printer->Annotate("constant_name", descriptor_->field(i));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ if (context_->HasGeneratedMethods(descriptor_)) {
+ GenerateIsInitialized(printer);
+ GenerateMessageSerializationMethods(printer);
+ GenerateEqualsAndHashCode(printer);
+ }
+
+
+ GenerateParseFromMethods(printer);
+ GenerateBuilder(printer);
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ // Carefully initialize the default instance in such a way that it doesn't
+ // conflict with other initialization.
+ printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
+ "classname",
+ name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Print(
+ "static {\n"
+ " DEFAULT_INSTANCE = new $classname$();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public static $classname$ getDefaultInstance() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // 'of' method for Wrappers
+ if (IsWrappersProtoFile(descriptor_->file())) {
+ printer->Print(
+ "public static $classname$ of($field_type$ value) {\n"
+ " return newBuilder().setValue(value).build();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+ }
+
+ GenerateParser(printer);
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+ // the outer class's FileDescriptor.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .Generate(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateMessageSerializationMethods(
+ io::Printer* printer) {
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+ printer->Print(
+ "@java.lang.Override\n"
+ "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
+ " throws java.io.IOException {\n");
+ printer->Indent();
+
+ if (HasPackedFields(descriptor_)) {
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks
+ // for each packed field, just call getSerializedSize() up front. In most
+ // cases, getSerializedSize() will have already been called anyway by one
+ // of the wrapper writeTo() methods, making this call cheap.
+ printer->Print("getSerializedSize();\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
+ } else {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "ver", GeneratedCodeVersionSuffix());
+ }
+ }
+
+ // Merge the fields and the extension ranges, both sorted by field number.
+ for (int i = 0, j = 0;
+ i < descriptor_->field_count() || j < sorted_extensions.size();) {
+ if (i == descriptor_->field_count()) {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ } else if (j == sorted_extensions.size()) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ }
+ }
+
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print("unknownFields.writeAsMessageSetTo(output);\n");
+ } else {
+ printer->Print("unknownFields.writeTo(output);\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "@java.lang.Override\n"
+ "public int getSerializedSize() {\n"
+ " int size = memoizedSize;\n"
+ " if (size != -1) return size;\n"
+ "\n");
+ printer->Indent();
+
+ printer->Print("size = 0;\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
+ } else {
+ printer->Print("size += extensionsSerializedSize();\n");
+ }
+ }
+
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n");
+ } else {
+ printer->Print("size += unknownFields.getSerializedSize();\n");
+ }
+
+ printer->Print(
+ "memoizedSize = size;\n"
+ "return size;\n");
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ printer->Print(
+ "public static $classname$ parseFrom(\n"
+ " java.nio.ByteBuffer data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " java.nio.ByteBuffer data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " byte[] data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseWithIOException(PARSER, input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseWithIOException(PARSER, input, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(java.io.InputStream "
+ "input)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseDelimitedWithIOException(PARSER, input);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseDelimitedWithIOException(PARSER, input, "
+ "extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseWithIOException(PARSER, input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessage$ver$\n"
+ " .parseWithIOException(PARSER, input, extensionRegistry);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+}
+
+void ImmutableMessageGenerator::GenerateSerializeOneField(
+ io::Printer* printer, const FieldDescriptor* field) {
+ field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range) {
+ printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
+ StrCat(range->end));
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
+ // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+ printer->Print(
+ "@java.lang.Override\n"
+ "public Builder newBuilderForType() { return newBuilder(); }\n");
+
+ printer->Print(
+ "public static Builder newBuilder() {\n"
+ " return DEFAULT_INSTANCE.toBuilder();\n"
+ "}\n"
+ "public static Builder newBuilder($classname$ prototype) {\n"
+ " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder toBuilder() {\n"
+ " return this == DEFAULT_INSTANCE\n"
+ " ? new Builder() : new Builder().mergeFrom(this);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "protected Builder newBuilderForType(\n"
+ " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
+ " Builder builder = new Builder(parent);\n"
+ " return builder;\n"
+ "}\n",
+ "ver", GeneratedCodeVersionSuffix());
+
+ MessageBuilderGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
+}
+
+void ImmutableMessageGenerator::GenerateDescriptorMethods(
+ io::Printer* printer) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print(
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+ }
+ std::vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
+ }
+ if (!map_fields.empty()) {
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "@java.lang.Override\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGet$capitalized_name$();\n",
+ "number", StrCat(field->number()), "capitalized_name",
+ info->capitalized_name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ }
+ printer->Print(
+ "@java.lang.Override\n"
+ "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
+ " internalGetFieldAccessorTable() {\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). -1 means not yet computed. 0 means false and 1 means
+ // true.
+ printer->Print("private byte memoizedIsInitialized = -1;\n");
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final boolean isInitialized() {\n");
+ printer->Indent();
+
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ printer->Print(
+ "byte isInitialized = memoizedIsInitialized;\n"
+ "if (isInitialized == 1) return true;\n"
+ "if (isInitialized == 0) return false;\n"
+ "\n");
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ "}\n",
+ "type",
+ name_resolver_->GetImmutableClassName(field->message_type()),
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_OPTIONAL:
+ printer->Print(
+ "if (has$name$()) {\n"
+ " if (!get$name$().isInitialized()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$Map().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type",
+ MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type",
+ name_resolver_->GetImmutableClassName(field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " return false;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(" memoizedIsInitialized = 1;\n");
+
+ printer->Print(
+ " return true;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+namespace {
+bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return false;
+ }
+ if (HasHasbit(field)) {
+ return true;
+ }
+ return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(field);
+}
+} // namespace
+
+void ImmutableMessageGenerator::GenerateEqualsAndHashCode(
+ io::Printer* printer) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public boolean equals(");
+ printer->Print("final java.lang.Object obj) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (obj == this) {\n"
+ " return true;\n"
+ "}\n"
+ "if (!(obj instanceof $classname$)) {\n"
+ " return super.equals(obj);\n"
+ "}\n"
+ "$classname$ other = ($classname$) obj;\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!IsRealOneof(field)) {
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
+ printer->Print(
+ "if (has$name$() != other.has$name$()) return false;\n"
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ printer->Indent();
+ }
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ if (check_has_bits) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ }
+
+ // Compare oneofs.
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "if (!get$oneof_capitalized_name$Case().equals("
+ "other.get$oneof_capitalized_name$Case())) return false;\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
+ printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
+ context_->GetOneofGeneratorInfo(oneof)->name);
+ printer->Indent();
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print("case $field_number$:\n", "field_number",
+ StrCat(field->number()));
+ printer->Indent();
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Print(
+ "case 0:\n"
+ "default:\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ // Always consider unknown fields for equality. This will sometimes return
+ // false for non-canonical ordering when running in LITE_RUNTIME but it's
+ // the best we can do.
+ printer->Print(
+ "if (!unknownFields.equals(other.unknownFields)) return false;\n");
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!getExtensionFields().equals(other.getExtensionFields()))\n"
+ " return false;\n");
+ }
+ printer->Print("return true;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public int hashCode() {\n");
+ printer->Indent();
+ printer->Print("if (memoizedHashCode != 0) {\n");
+ printer->Indent();
+ printer->Print("return memoizedHashCode;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "int hash = 41;\n");
+
+ // If we output a getDescriptor() method, use that as it is more efficient.
+ if (descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+ } else {
+ printer->Print("hash = (19 * hash) + getDescriptor().hashCode();\n");
+ }
+
+ // hashCode non-oneofs.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!IsRealOneof(field)) {
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
+ printer->Print("if (has$name$()) {\n", "name", info->capitalized_name);
+ printer->Indent();
+ }
+ field_generators_.get(field).GenerateHashCode(printer);
+ if (check_has_bits) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ }
+
+ // hashCode oneofs.
+ for (auto oneof : oneofs_) {
+ printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
+ context_->GetOneofGeneratorInfo(oneof)->name);
+ printer->Indent();
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print("case $field_number$:\n", "field_number",
+ StrCat(field->number()));
+ printer->Indent();
+ field_generators_.get(field).GenerateHashCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ }
+ printer->Print(
+ "case 0:\n"
+ "default:\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print("hash = hashFields(hash, getExtensionFields());\n");
+ }
+
+ printer->Print("hash = (29 * hash) + unknownFields.hashCode();\n");
+ printer->Print(
+ "memoizedHashCode = hash;\n"
+ "return hash;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageGenerator::GenerateExtensionRegistrationCode(
+ io::Printer* printer) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .GenerateRegistrationCode(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateExtensionRegistrationCode(printer);
+ }
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateParsingConstructor(
+ io::Printer* printer) {
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "private $classname$(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Initialize all fields to default.
+ printer->Print(
+ "this();\n"
+ "if (extensionRegistry == null) {\n"
+ " throw new java.lang.NullPointerException();\n"
+ "}\n");
+
+ // Use builder bits to track mutable repeated fields.
+ int totalBuilderBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const ImmutableFieldGenerator& field =
+ field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int mutable_$bit_field_name$ = 0;\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+
+ printer->Print("try {\n");
+ printer->Indent();
+
+ printer->Print(
+ "boolean done = false;\n"
+ "while (!done) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " done = true;\n"
+ " break;\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32_t tag = WireFormatLite::MakeTag(
+ field->number(), WireFormat::WireTypeForFieldType(field->type()));
+
+ printer->Print("case $tag$: {\n", "tag",
+ StrCat(static_cast<int32_t>(tag)));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32_t packed_tag = WireFormatLite::MakeTag(
+ field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print("case $tag$: {\n", "tag",
+ StrCat(static_cast<int32_t>(packed_tag)));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+ }
+
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(\n"
+ " input, unknownFields, extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ "}\n"); // while (!done)
+
+ printer->Outdent();
+ printer->Print(
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw e.setUnfinishedMessage(this);\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e).setUnfinishedMessage(this);\n"
+ "} finally {\n");
+ printer->Indent();
+
+ // Make repeated field list immutable.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ field_generators_.get(field).GenerateParsingDoneCode(printer);
+ }
+
+ // Make unknown fields immutable.
+ printer->Print("this.unknownFields = unknownFields.build();\n");
+
+ // Make extensions immutable.
+ printer->Print("makeExtensionsImmutable();\n");
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // finally
+ "}\n");
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
+ printer->Print(
+ "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
+ " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n",
+ "visibility",
+ ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public"
+ : "private",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Print(
+ "@java.lang.Override\n"
+ "public $classname$ parsePartialFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ "classname", descriptor_->name());
+ if (context_->HasGeneratedMethods(descriptor_)) {
+ printer->Print(" return new $classname$(input, extensionRegistry);\n",
+ "classname", descriptor_->name());
+ } else {
+ // When parsing constructor isn't generated, use builder to parse
+ // messages. Note, will fallback to use reflection based mergeFieldFrom()
+ // in AbstractMessage.Builder.
+ printer->Indent();
+ printer->Print(
+ "Builder builder = newBuilder();\n"
+ "try {\n"
+ " builder.mergeFrom(input, extensionRegistry);\n"
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw e.setUnfinishedMessage(builder.buildPartial());\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(\n"
+ " builder.buildPartial());\n"
+ "}\n"
+ "return builder.buildPartial();\n");
+ printer->Outdent();
+ }
+ printer->Print("}\n");
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+
+ printer->Print(
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n"
+ "@java.lang.Override\n"
+ "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!IsRealOneof(descriptor_->field(i))) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+}
+
+// ===================================================================
+void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) {
+ printer->Print(
+ "protected com.google.protobuf.MutableMessage\n"
+ " internalMutableDefault() {\n"
+ " return MutableDefaultLoader.get();\n"
+ "}\n"
+ "\n"
+ "private static final class MutableDefaultLoader {\n"
+ " private static final java.lang.Object defaultOrRuntimeException;\n"
+ " static {\n"
+ " java.lang.Object local;\n"
+ " try {\n"
+ " local = internalMutableDefault(\"$mutable_name$\");\n"
+ " } catch (java.lang.RuntimeException e) {\n"
+ " local = e;\n"
+ " }\n"
+ " defaultOrRuntimeException = local;\n"
+ " }\n"
+ "\n"
+ " private MutableDefaultLoader() {}\n"
+ "\n"
+ " public static com.google.protobuf.MutableMessage get() {\n"
+ " if (defaultOrRuntimeException\n"
+ " instanceof java.lang.RuntimeException) {\n"
+ " throw (java.lang.RuntimeException) defaultOrRuntimeException;\n"
+ " }\n"
+ " return\n"
+ " (com.google.protobuf.MutableMessage) "
+ "defaultOrRuntimeException;\n"
+ " }\n"
+ "}\n",
+ "mutable_name", name_resolver_->GetJavaMutableClassName(descriptor_));
+}
+
+void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const {
+ printer->Print(
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "@com.google.protobuf.kotlin.ProtoDslMarker\n");
+ printer->Print(
+ "public class Dsl private constructor(\n"
+ " private val _builder: $message$.Builder\n"
+ ") {\n"
+ " public companion object {\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @kotlin.PublishedApi\n"
+ " internal fun _create(builder: $message$.Builder): Dsl = "
+ "Dsl(builder)\n"
+ " }\n"
+ "\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @kotlin.PublishedApi\n"
+ " internal fun _build(): $message$ = _builder.build()\n",
+ "message", name_resolver_->GetClassName(descriptor_, true));
+
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateKotlinDslMembers(printer);
+ }
+
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
+ " @JvmName(\"get$oneof_capitalized_name$Case\")\n"
+ " get() = _builder.get$oneof_capitalized_name$Case()\n\n"
+ "public fun clear$oneof_capitalized_name$() {\n"
+ " _builder.clear$oneof_capitalized_name$()\n"
+ "}\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
+ name_resolver_->GetClassName(descriptor_, true));
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ GenerateKotlinExtensions(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageGenerator::GenerateKotlinMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
+ "kotlin.Unit): "
+ "$message$ "
+ "=\n"
+ " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
+ "}._build()\n",
+ "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
+ "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
+ "message", name_resolver_->GetClassName(descriptor_, true));
+
+ printer->Print("public object $name$Kt {\n", "name", descriptor_->name());
+ printer->Indent();
+ GenerateKotlinDsl(printer);
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateKotlinMembers(printer);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
+ "kotlin.Unit): "
+ "$message$ =\n"
+ " $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
+ "}._build()\n",
+ "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
+ name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateTopLevelKotlinMembers(printer);
+ }
+}
+
+void ImmutableMessageGenerator::GenerateKotlinExtensions(
+ io::Printer* printer) const {
+ std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+
+ printer->Print(
+ "@Suppress(\"UNCHECKED_CAST\")\n"
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun <T> get(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
+ " return if (extension.isRepeated) {\n"
+ " get(extension as com.google.protobuf.ExtensionLite<$message$, "
+ "List<*>>) as T\n"
+ " } else {\n"
+ " _builder.getExtension(extension)\n"
+ " }\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
+ "public operator fun <E> get(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+ "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
+ " return com.google.protobuf.kotlin.ExtensionList(extension, "
+ "_builder.getExtension(extension))\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun contains(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, *>): "
+ "Boolean {\n"
+ " return _builder.hasExtension(extension)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun clear(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, *>) "
+ "{\n"
+ " _builder.clearExtension(extension)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.PublishedApi\n"
+ "internal fun <T> setExtension(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, T>, "
+ "value: T) {\n"
+ " _builder.setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <T : Comparable<T>> set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+ " value: T\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, "
+ "com.google.protobuf.ByteString>,\n"
+ " value: com.google.protobuf.ByteString\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+ " value: T\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.add(value: E) {\n"
+ " _builder.addExtension(this.extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <E> "
+ "com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.plusAssign"
+ "(value: E) {\n"
+ " add(value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.addAll(values: Iterable<E>) {\n"
+ " for (value in values) {\n"
+ " add(value)\n"
+ " }\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <E> "
+ "com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.plusAssign(values: "
+ "Iterable<E>) {\n"
+ " addAll(values)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.set(index: Int, value: "
+ "E) {\n"
+ " _builder.setExtension(this.extension, index, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline fun com.google.protobuf.kotlin.ExtensionList<*, "
+ "$message$>.clear() {\n"
+ " clear(extension)\n"
+ "}\n\n",
+ "message", message_name);
+}
+
+void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
+ printer->Print(
+ "private static String getTypeUrl(\n"
+ " java.lang.String typeUrlPrefix,\n"
+ " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
+ " return typeUrlPrefix.endsWith(\"/\")\n"
+ " ? typeUrlPrefix + descriptor.getFullName()\n"
+ " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
+ "}\n"
+ "\n"
+ "private static String getTypeNameFromTypeUrl(\n"
+ " java.lang.String typeUrl) {\n"
+ " int pos = typeUrl.lastIndexOf('/');\n"
+ " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
+ "}\n"
+ "\n"
+ "public static <T extends com.google.protobuf.Message> Any pack(\n"
+ " T message) {\n"
+ " return Any.newBuilder()\n"
+ " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
+ " message.getDescriptorForType()))\n"
+ " .setValue(message.toByteString())\n"
+ " .build();\n"
+ "}\n"
+ "\n"
+ "/**\n"
+ " * Packs a message using the given type URL prefix. The type URL will\n"
+ " * be constructed by concatenating the message type's full name to the\n"
+ " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
+ " * with \"/\" already.\n"
+ " */\n"
+ "public static <T extends com.google.protobuf.Message> Any pack(\n"
+ " T message, java.lang.String typeUrlPrefix) {\n"
+ " return Any.newBuilder()\n"
+ " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
+ " message.getDescriptorForType()))\n"
+ " .setValue(message.toByteString())\n"
+ " .build();\n"
+ "}\n"
+ "\n"
+ "public <T extends com.google.protobuf.Message> boolean is(\n"
+ " java.lang.Class<T> clazz) {\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+ " defaultInstance.getDescriptorForType().getFullName());\n"
+ "}\n"
+ "\n"
+ "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
+ "\n"
+ "@java.lang.SuppressWarnings(\"unchecked\")\n"
+ "public <T extends com.google.protobuf.Message> T unpack(\n"
+ " java.lang.Class<T> clazz)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " boolean invalidClazz = false;\n"
+ " if (cachedUnpackValue != null) {\n"
+ " if (cachedUnpackValue.getClass() == clazz) {\n"
+ " return (T) cachedUnpackValue;\n"
+ " }\n"
+ " invalidClazz = true;\n"
+ " }\n"
+ " if (invalidClazz || !is(clazz)) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " \"Type of the Any message does not match the given class.\");\n"
+ " }\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " T result = (T) defaultInstance.getParserForType()\n"
+ " .parseFrom(getValue());\n"
+ " cachedUnpackValue = result;\n"
+ " return result;\n"
+ "}\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.h
new file mode 100644
index 00000000..7ee4e431
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message.h
@@ -0,0 +1,153 @@
+// 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_JAVA_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+static const int kMaxStaticSize = 1 << 15; // aka 32k
+
+class MessageGenerator {
+ public:
+ explicit MessageGenerator(const Descriptor* descriptor);
+ virtual ~MessageGenerator();
+
+ // All static variables have to be declared at the top-level of the file
+ // so that we can control initialization order, which is important for
+ // DescriptorProto bootstrapping to work.
+ virtual void GenerateStaticVariables(io::Printer* printer,
+ int* bytecode_estimate) = 0;
+
+ // Output code which initializes the static variables generated by
+ // GenerateStaticVariables(). Returns an estimate of bytecode size.
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0;
+
+ // Generate the class itself.
+ virtual void Generate(io::Printer* printer) = 0;
+
+ // Generates the base interface that both the class and its builder
+ // implement
+ virtual void GenerateInterface(io::Printer* printer) = 0;
+
+ // Generate code to register all contained extensions with an
+ // ExtensionRegistry.
+ virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0;
+ virtual void GenerateKotlinDsl(io::Printer* printer) const = 0;
+ virtual void GenerateKotlinMembers(io::Printer* printer) const = 0;
+ virtual void GenerateTopLevelKotlinMembers(io::Printer* printer) const = 0;
+
+ protected:
+ const Descriptor* descriptor_;
+ std::set<const OneofDescriptor*> oneofs_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+class ImmutableMessageGenerator : public MessageGenerator {
+ public:
+ ImmutableMessageGenerator(const Descriptor* descriptor, Context* context);
+ virtual ~ImmutableMessageGenerator();
+
+ void Generate(io::Printer* printer) override;
+ void GenerateInterface(io::Printer* printer) override;
+ void GenerateExtensionRegistrationCode(io::Printer* printer) override;
+ void GenerateStaticVariables(io::Printer* printer,
+ int* bytecode_estimate) override;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateStaticVariableInitializers(io::Printer* printer) override;
+ void GenerateKotlinDsl(io::Printer* printer) const override;
+ void GenerateKotlinMembers(io::Printer* printer) const override;
+ void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
+
+ private:
+ void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateFieldAccessorTableInitializer(io::Printer* printer);
+
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateParseFromMethods(io::Printer* printer);
+ void GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateBuilder(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer);
+ void GenerateInitializers(io::Printer* printer);
+ void GenerateEqualsAndHashCode(io::Printer* printer);
+ void GenerateParser(io::Printer* printer);
+ void GenerateParsingConstructor(io::Printer* printer);
+ void GenerateMutableCopy(io::Printer* printer);
+ void GenerateKotlinExtensions(io::Printer* printer) const;
+ void GenerateAnyMethods(io::Printer* printer);
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.cc
new file mode 100644
index 00000000..ac72da8e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.cc
@@ -0,0 +1,712 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_message_builder.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum.h>
+#include <compiler/java/java_extension.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+std::string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+MessageBuilderGenerator::MessageBuilderGenerator(const Descriptor* descriptor,
+ Context* context)
+ : descriptor_(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A non-lite message generator is used to "
+ "generate lite messages.";
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (IsRealOneof(descriptor_->field(i))) {
+ oneofs_.insert(descriptor_->field(i)->containing_oneof());
+ }
+ }
+}
+
+MessageBuilderGenerator::~MessageBuilderGenerator() {}
+
+void MessageBuilderGenerator::Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+ } else {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage$ver$.Builder<Builder> "
+ "implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+ }
+ printer->Indent();
+
+ GenerateDescriptorMethods(printer);
+ GenerateCommonBuilderMethods(printer);
+
+ if (context_->HasGeneratedMethods(descriptor_)) {
+ GenerateIsInitialized(printer);
+ GenerateBuilderParsingMethods(printer);
+ }
+
+ // oneof
+ std::map<std::string, std::string> vars;
+ for (auto oneof : oneofs_) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
+ vars["oneof_capitalized_name"] =
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
+ vars["oneof_index"] = StrCat(oneof->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n");
+ printer->Print(" onChanged();\n");
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits +=
+ field_generators_.get(descriptor_->field(i)).GetNumBitsForBuilder();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderMembers(printer);
+ }
+
+ // Override methods declared in GeneratedMessage to return the concrete
+ // generated type so callsites won't depend on GeneratedMessage. This
+ // is needed to keep binary compatibility when we change generated code
+ // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+ // we changed all generated code to subclass GeneratedMessageV3).
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final Builder setUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return super.setUnknownFields(unknownFields);\n"
+ "}\n"
+ "\n"
+ "@java.lang.Override\n"
+ "public final Builder mergeUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return super.mergeUnknownFields(unknownFields);\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print(
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+ }
+ std::vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
+ }
+ if (!map_fields.empty()) {
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGet$capitalized_name$();\n",
+ "number", StrCat(field->number()), "capitalized_name",
+ info->capitalized_name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return internalGetMutable$capitalized_name$();\n",
+ "number", StrCat(field->number()), "capitalized_name",
+ info->capitalized_name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ }
+ printer->Print(
+ "@java.lang.Override\n"
+ "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
+ " internalGetFieldAccessorTable() {\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateCommonBuilderMethods(
+ io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "private Builder(\n"
+ " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
+ " super(parent);\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver",
+ GeneratedCodeVersionSuffix());
+
+ printer->Print(
+ "private void maybeForceBuilderInitialization() {\n"
+ " if (com.google.protobuf.GeneratedMessage$ver$\n"
+ " .alwaysUseFieldBuilders) {\n",
+ "ver", GeneratedCodeVersionSuffix());
+
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!IsRealOneof(descriptor_->field(i))) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateFieldBuilderInitializationCode(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public Builder clear() {\n"
+ " super.clear();\n");
+
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!IsRealOneof(descriptor_->field(i))) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderClearCode(printer);
+ }
+ }
+
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "$oneof_name$Case_ = 0;\n"
+ "$oneof_name$_ = null;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptorForType() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+ // LITE runtime implements this in GeneratedMessageLite.
+ printer->Print(
+ "@java.lang.Override\n"
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return $classname$.getDefaultInstance();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public $classname$ build() {\n"
+ " $classname$ result = buildPartial();\n"
+ " if (!result.isInitialized()) {\n"
+ " throw newUninitializedMessageException(result);\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public $classname$ buildPartial() {\n"
+ " $classname$ result = new $classname$(this);\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+
+ int totalBuilderBits = 0;
+ int totalMessageBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const ImmutableFieldGenerator& field =
+ field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ totalMessageBits += field.GetNumBitsForMessage();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ int totalMessageInts = (totalMessageBits + 31) / 32;
+
+ // Local vars for from and to bit fields to avoid accessing the builder and
+ // message over and over for these fields. Seems to provide a slight
+ // perforamance improvement in micro benchmark and this is also what proto1
+ // code does.
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+
+ // Output generation code for each field.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
+ }
+
+ // Copy the bit field results to the generated message
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+
+ for (auto oneof : oneofs_) {
+ printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(" onBuilt();\n");
+
+ printer->Print(
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Override methods declared in GeneratedMessage to return the concrete
+ // generated type so callsites won't depend on GeneratedMessage. This
+ // is needed to keep binary compatibility when we change generated code
+ // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+ // we changed all generated code to subclass GeneratedMessageV3).
+ printer->Print(
+ "@java.lang.Override\n"
+ "public Builder clone() {\n"
+ " return super.clone();\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder setField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " java.lang.Object value) {\n"
+ " return super.setField(field, value);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder clearField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
+ " return super.clearField(field);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder clearOneof(\n"
+ " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n"
+ " return super.clearOneof(oneof);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder setRepeatedField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " int index, java.lang.Object value) {\n"
+ " return super.setRepeatedField(field, index, value);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public Builder addRepeatedField(\n"
+ " com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+ " java.lang.Object value) {\n"
+ " return super.addRepeatedField(field, value);\n"
+ "}\n");
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public <Type> Builder setExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, Type> extension,\n"
+ " Type value) {\n"
+ " return super.setExtension(extension, value);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public <Type> Builder setExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, java.util.List<Type>> extension,\n"
+ " int index, Type value) {\n"
+ " return super.setExtension(extension, index, value);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public <Type> Builder addExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, java.util.List<Type>> extension,\n"
+ " Type value) {\n"
+ " return super.addExtension(extension, value);\n"
+ "}\n"
+ "@java.lang.Override\n"
+ "public <Type> Builder clearExtension(\n"
+ " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+ " $classname$, ?> extension) {\n"
+ " return super.clearExtension(extension);\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ }
+
+ // -----------------------------------------------------------------
+
+ if (context_->HasGeneratedMethods(descriptor_)) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
+ " if (other instanceof $classname$) {\n"
+ " return mergeFrom(($classname$)other);\n"
+ " } else {\n"
+ " super.mergeFrom(other);\n"
+ " return this;\n"
+ " }\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public Builder mergeFrom($classname$ other) {\n"
+ // Optimization: If other is the default instance, we know none of its
+ // fields are set so we can skip the merge.
+ " if (other == $classname$.getDefaultInstance()) return this;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!IsRealOneof(descriptor_->field(i))) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateMergingCode(printer);
+ }
+ }
+
+ // Merge oneof fields.
+ for (auto oneof : oneofs_) {
+ printer->Print("switch (other.get$oneof_capitalized_name$Case()) {\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
+ printer->Indent();
+ for (int j = 0; j < oneof->field_count(); j++) {
+ const FieldDescriptor* field = oneof->field(j);
+ printer->Print("case $field_name$: {\n", "field_name",
+ ToUpper(field->name()));
+ printer->Indent();
+ field_generators_.get(field).GenerateMergingCode(printer);
+ printer->Print("break;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print(
+ "case $cap_oneof_name$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ "cap_oneof_name",
+ ToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ printer->Outdent();
+
+ // if message type has extensions
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(" this.mergeExtensionFields(other);\n");
+ }
+
+ printer->Print(" this.mergeUnknownFields(other.unknownFields);\n");
+
+ printer->Print(" onChanged();\n");
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateBuilderParsingMethods(
+ io::Printer* printer) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public Builder mergeFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " $classname$ parsedMessage = null;\n"
+ " try {\n"
+ " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
+ " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
+ " throw e.unwrapIOException();\n"
+ " } finally {\n"
+ " if (parsedMessage != null) {\n"
+ " mergeFrom(parsedMessage);\n"
+ " }\n"
+ " }\n"
+ " return this;\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::GenerateIsInitialized(io::Printer* printer) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final boolean isInitialized() {\n");
+ printer->Indent();
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " return false;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ "}\n",
+ "type",
+ name_resolver_->GetImmutableClassName(field->message_type()),
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_OPTIONAL:
+ printer->Print(
+ "if (has$name$()) {\n"
+ " if (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$Map().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type",
+ MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type",
+ name_resolver_->GetImmutableClassName(field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " return false;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return true;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.h
new file mode 100644
index 00000000..7d6da17d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder.h
@@ -0,0 +1,89 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderGenerator {
+ public:
+ explicit MessageBuilderGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer);
+ void GenerateBuilderParsingMethods(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+ std::set<const OneofDescriptor*> oneofs_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.cc
new file mode 100644
index 00000000..83f5d072
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.cc
@@ -0,0 +1,151 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_message_builder_lite.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum.h>
+#include <compiler/java/java_extension.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A lite message generator is used to "
+ "generate non-lite messages.";
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (IsRealOneof(descriptor_->field(i))) {
+ oneofs_.insert(descriptor_->field(i)->containing_oneof());
+ }
+ }
+}
+
+MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
+
+void MessageBuilderLiteGenerator::Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "extendible",
+ descriptor_->extension_range_count() > 0 ? "Extendable" : "");
+ printer->Indent();
+
+ GenerateCommonBuilderMethods(printer);
+
+ // oneof
+ std::map<std::string, std::string> vars;
+ for (auto oneof : oneofs_) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
+ vars["oneof_capitalized_name"] =
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
+ vars["oneof_index"] = StrCat(oneof->index());
+
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "@java.lang.Override\n"
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return instance.get$oneof_capitalized_name$Case();\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$oneof_capitalized_name$();\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderMembers(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderLiteGenerator::GenerateCommonBuilderMethods(
+ io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " super(DEFAULT_INSTANCE);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.h
new file mode 100644
index 00000000..8ad4e94b
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_builder_lite.h
@@ -0,0 +1,86 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderLiteGenerator {
+ public:
+ explicit MessageBuilderLiteGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderLiteGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+ std::set<const OneofDescriptor*> oneofs_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.cc
new file mode 100644
index 00000000..394735d1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.cc
@@ -0,0 +1,1494 @@
+// 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 <map>
+#include <string>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_message_field.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ (*variables)["kt_type"] = (*variables)["type"];
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->message_type());
+ (*variables)["group_or_message"] =
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group"
+ : "Message";
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["on_changed"] = "onChanged();";
+ (*variables)["ver"] = GeneratedCodeVersionSuffix();
+ (*variables)["get_parser"] =
+ ExposePublicParser(descriptor->message_type()->file()) ? "PARSER"
+ : "parser()";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["set_has_field_bit_builder"] =
+ GenerateSetBit(builderBitIndex) + ";";
+ (*variables)["clear_has_field_bit_builder"] =
+ GenerateClearBit(builderBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_builder"] = "";
+ (*variables)["clear_has_field_bit_builder"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != null";
+ }
+
+ // For repeated 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
+
+// ===================================================================
+
+ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
+
+int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
+ return GetNumBitsForMessage();
+}
+
+void ImmutableMessageFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having a method specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private $type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (HasHasbit(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ } else {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $name$_ != null;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$() {\n"
+ " return get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+}
+
+void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
+ io::Printer* printer, const char* regular_case,
+ const char* nested_builder_case) const {
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
+ io::Printer* printer, const char* method_prototype,
+ const char* regular_case, const char* nested_builder_case,
+ const char* trailing_code) const {
+ printer->Print(variables_, method_prototype);
+ printer->Annotate("{", "}", descriptor_);
+ printer->Print(" {\n");
+ printer->Indent();
+ PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+ if (trailing_code != NULL) {
+ printer->Print(variables_, trailing_code);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // When using nested-builders, the code initially works just like the
+ // non-nested builder case. It only creates a nested builder lazily on
+ // demand and then forever delegates to it after creation.
+
+ bool has_hasbit = HasHasbit(descriptor_);
+
+ printer->Print(variables_, "private $type$ $name$_;\n");
+
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields
+ // are ignored.
+ "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
+
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ if (has_hasbit) {
+ printer->Print(
+ variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_builder$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ } else {
+ printer->Print(
+ variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $name$Builder_ != null || $name$_ != null;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ // Field getField()
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ PrintNestedBuilderFunction(
+ printer, "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
+ "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
+ "return $name$Builder_.getMessage();\n", NULL);
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
+
+ "if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ "}\n"
+ "$name$_ = value;\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.setMessage(value);\n",
+
+ "$set_has_field_bit_builder$\n"
+ "return this;\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue)",
+
+ "$name$_ = builderForValue.build();\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.setMessage(builderForValue.build());\n",
+
+ "$set_has_field_bit_builder$\n"
+ "return this;\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
+
+ has_hasbit
+ ? "if ($get_has_field_bit_builder$ &&\n"
+ " $name$_ != null &&\n"
+ " $name$_ != $type$.getDefaultInstance()) {\n"
+ " $name$_ =\n"
+ " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+ "} else {\n"
+ " $name$_ = value;\n"
+ "}\n"
+ "$on_changed$\n"
+ : "if ($name$_ != null) {\n"
+ " $name$_ =\n"
+ " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+ "} else {\n"
+ " $name$_ = value;\n"
+ "}\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.mergeFrom(value);\n",
+
+ "$set_has_field_bit_builder$\n"
+ "return this;\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
+
+ "$name$_ = null;\n"
+ "$on_changed$\n",
+
+ has_hasbit ? "$name$Builder_.clear();\n"
+ : "$name$_ = null;\n"
+ "$name$Builder_ = null;\n",
+
+ "$clear_has_field_bit_builder$\n"
+ "return this;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder "
+ "${$get$capitalized_name$Builder$}$() {\n"
+ " $set_has_field_bit_builder$\n"
+ " $on_changed$\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " return $name$_ == null ?\n"
+ " $type$.getDefaultInstance() : $name$_;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " get$capitalized_name$(),\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const {
+ if (HasHasbit(descriptor_)) {
+ printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n");
+ }
+}
+
+void ImmutableMessageFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {}
+
+void ImmutableMessageFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ if (HasHasbit(descriptor_)) {
+ PrintNestedBuilderCondition(printer, "$name$_ = null;\n",
+
+ "$name$Builder_.clear();\n");
+ printer->Print(variables_, "$clear_has_field_bit_builder$\n");
+ } else {
+ PrintNestedBuilderCondition(printer, "$name$_ = null;\n",
+
+ "$name$_ = null;\n"
+ "$name$Builder_ = null;\n");
+ }
+}
+
+void ImmutableMessageFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " merge$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ if (HasHasbit(descriptor_)) {
+ printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n");
+ printer->Indent();
+ PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n",
+ "result.$name$_ = $name$Builder_.build();\n");
+ printer->Outdent();
+ printer->Print(variables_,
+ " $set_has_field_bit_to_local$;\n"
+ "}\n");
+ } else {
+ PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n",
+ "result.$name$_ = $name$Builder_.build();\n");
+ }
+}
+
+void ImmutableMessageFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$.Builder subBuilder = null;\n"
+ "if ($is_field_present_message$) {\n"
+ " subBuilder = $name$_.toBuilder();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$name$_ = input.readGroup($number$, $type$.$get_parser$,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_ = input.readMessage($type$.$get_parser$, "
+ "extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom($name$_);\n"
+ " $name$_ = subBuilder.buildPartial();\n"
+ "}\n"
+ "$set_has_field_bit_message$\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ // noop for messages.
+}
+
+void ImmutableMessageFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$())) return false;\n");
+}
+
+void ImmutableMessageFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+std::string ImmutableMessageFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldGenerator::ImmutableMessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : ImmutableMessageFieldGenerator(descriptor, messageBitIndex,
+ builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldGenerator::~ImmutableMessageOneofFieldGenerator() {}
+
+void ImmutableMessageOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // When using nested-builders, the code initially works just like the
+ // non-nested builder case. It only creates a nested builder lazily on
+ // demand and then forever delegates to it after creation.
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields
+ // are ignored.
+ "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
+
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field getField()
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ PrintNestedBuilderFunction(
+ printer,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
+
+ "if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ "}\n"
+ "return $type$.getDefaultInstance();\n",
+
+ "if ($has_oneof_case_message$) {\n"
+ " return $name$Builder_.getMessage();\n"
+ "}\n"
+ "return $type$.getDefaultInstance();\n",
+
+ NULL);
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
+
+ "if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ "}\n"
+ "$oneof_name$_ = value;\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.setMessage(value);\n",
+
+ "$set_oneof_case_message$;\n"
+ "return this;\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue)",
+
+ "$oneof_name$_ = builderForValue.build();\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.setMessage(builderForValue.build());\n",
+
+ "$set_oneof_case_message$;\n"
+ "return this;\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
+
+ "if ($has_oneof_case_message$ &&\n"
+ " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+ " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+ " .mergeFrom(value).buildPartial();\n"
+ "} else {\n"
+ " $oneof_name$_ = value;\n"
+ "}\n"
+ "$on_changed$\n",
+
+ "if ($has_oneof_case_message$) {\n"
+ " $name$Builder_.mergeFrom(value);\n"
+ "}\n"
+ "$name$Builder_.setMessage(value);\n",
+
+ "$set_oneof_case_message$;\n"
+ "return this;\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
+
+ "if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " $on_changed$\n"
+ "}\n",
+
+ "if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ "}\n"
+ "$name$Builder_.clear();\n",
+
+ "return this;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder "
+ "${$get$capitalized_name$Builder$}$() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$() {\n"
+ " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " ${$get$capitalized_name$FieldBuilder$}$() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = $type$.getDefaultInstance();\n"
+ " }\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " ($type$) $oneof_name$_,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $on_changed$;\n"
+ " return $name$Builder_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "if ($has_oneof_case_message$) {\n");
+ printer->Indent();
+
+ PrintNestedBuilderCondition(
+ printer, "result.$oneof_name$_ = $oneof_name$_;\n",
+
+ "result.$oneof_name$_ = $name$Builder_.build();\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "merge$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$.Builder subBuilder = null;\n"
+ "if ($has_oneof_case_message$) {\n"
+ " subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(
+ variables_,
+ "$oneof_name$_ = input.readGroup($number$, $type$.$get_parser$,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(
+ variables_,
+ "$oneof_name$_ =\n"
+ " input.readMessage($type$.$get_parser$, extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
+ " $oneof_name$_ = subBuilder.buildPartial();\n"
+ "}\n");
+ printer->Print(variables_, "$set_oneof_case_message$;\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldGenerator::RepeatedImmutableMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableMessageFieldGenerator::
+ ~RepeatedImmutableMessageFieldGenerator() {}
+
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having methods specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> \n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index);\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private java.util.List<$type$> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " ${$get$capitalized_name$OrBuilderList$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$(\n"
+ " int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
+ io::Printer* printer, const char* regular_case,
+ const char* nested_builder_case) const {
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
+ io::Printer* printer, const char* method_prototype,
+ const char* regular_case, const char* nested_builder_case,
+ const char* trailing_code) const {
+ printer->Print(variables_, method_prototype);
+ printer->Annotate("{", "}", descriptor_);
+ printer->Print(" {\n");
+ printer->Indent();
+ PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+ if (trailing_code != NULL) {
+ printer->Print(variables_, trailing_code);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // When using nested-builders, the code initially works just like the
+ // non-nested builder case. It only creates a nested builder lazily on
+ // demand and then forever delegates to it after creation.
+
+ printer->Print(
+ variables_,
+ // Used when the builder is null.
+ // 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 reference 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"
+ "\n");
+
+ printer->Print(
+ variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+ "\n");
+
+ // The comments above the methods below are based on a hypothetical
+ // repeated field of type "Field" called "RepeatedField".
+
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$()",
+
+ "return java.util.Collections.unmodifiableList($name$_);\n",
+ "return $name$Builder_.getMessageList();\n",
+
+ NULL);
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer, "$deprecation$public int ${$get$capitalized_name$Count$}$()",
+
+ "return $name$_.size();\n", "return $name$Builder_.getCount();\n",
+
+ NULL);
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index)",
+
+ "return $name$_.get(index);\n",
+
+ "return $name$Builder_.getMessage(index);\n",
+
+ NULL);
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$ value)",
+ "if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ "}\n"
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.set(index, value);\n"
+ "$on_changed$\n",
+ "$name$Builder_.setMessage(index, value);\n", "return this;\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$.Builder builderForValue)",
+
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.set(index, builderForValue.build());\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.setMessage(index, builderForValue.build());\n",
+
+ "return this;\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value)",
+
+ "if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ "}\n"
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.add(value);\n"
+
+ "$on_changed$\n",
+
+ "$name$Builder_.addMessage(value);\n",
+
+ "return this;\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " int index, $type$ value)",
+
+ "if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ "}\n"
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.add(index, value);\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.addMessage(index, value);\n",
+
+ "return this;\n");
+
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue)",
+
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.add(builderForValue.build());\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.addMessage(builderForValue.build());\n",
+
+ "return this;\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " int index, $type$.Builder builderForValue)",
+
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.add(index, builderForValue.build());\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.addMessage(index, builderForValue.build());\n",
+
+ "return this;\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $type$> values)",
+
+ "ensure$capitalized_name$IsMutable();\n"
+ "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.addAllMessages(values);\n",
+
+ "return this;\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
+
+ "$name$_ = java.util.Collections.emptyList();\n"
+ "$clear_mutable_bit_builder$;\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.clear();\n",
+
+ "return this;\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(
+ printer,
+ "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index)",
+
+ "ensure$capitalized_name$IsMutable();\n"
+ "$name$_.remove(index);\n"
+ "$on_changed$\n",
+
+ "$name$Builder_.remove(index);\n",
+
+ "return this;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$(\n"
+ " int index) {\n"
+ " if ($name$Builder_ == null) {\n"
+ " return $name$_.get(index);"
+ " } else {\n"
+ " return $name$Builder_.getMessageOrBuilder(index);\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " ${$get$capitalized_name$OrBuilderList$}$() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilderList();\n"
+ " } else {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder "
+ "${$add$capitalized_name$Builder$}$() {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " $type$.getDefaultInstance());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public $type$.Builder ${$add$capitalized_name$Builder$}$(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " index, $type$.getDefaultInstance());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.util.List<$type$.Builder> \n"
+ " ${$get$capitalized_name$BuilderList$}$() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+ "}\n"
+ "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new "
+ "com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " $get_mutable_bit_builder$,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutableMessageFieldGenerator::
+ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ PrintNestedBuilderCondition(printer,
+ "$name$_ = java.util.Collections.emptyList();\n"
+ "$clear_mutable_bit_builder$;\n",
+
+ "$name$Builder_.clear();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ // The code below does two optimizations (non-nested builder case):
+ // 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.
+ PrintNestedBuilderCondition(
+ printer,
+ "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",
+
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if ($name$Builder_.isEmpty()) {\n"
+ " $name$Builder_.dispose();\n"
+ " $name$Builder_ = null;\n"
+ " $name$_ = other.$name$_;\n"
+ " $clear_mutable_bit_builder$;\n"
+ " $name$Builder_ = \n"
+ " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders "
+ "?\n"
+ " get$capitalized_name$FieldBuilder() : null;\n"
+ " } else {\n"
+ " $name$Builder_.addAllMessages(other.$name$_);\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ // The code below (non-nested builder case) ensures that the result has an
+ // immutable list. If our list is immutable, we can just reuse it. If not,
+ // we make it immutable.
+ PrintNestedBuilderCondition(
+ printer,
+ "if ($get_mutable_bit_builder$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ " $clear_mutable_bit_builder$;\n"
+ "}\n"
+ "result.$name$_ = $name$_;\n",
+
+ "result.$name$_ = $name$Builder_.build();\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<$type$>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(
+ variables_,
+ "$name$_.add(input.readGroup($number$, $type$.$get_parser$,\n"
+ " extensionRegistry));\n");
+ } else {
+ printer->Print(
+ variables_,
+ "$name$_.add(\n"
+ " input.readMessage($type$.$get_parser$, extensionRegistry));\n");
+ }
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$group_or_message$($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List())) return false;\n");
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+std::string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.h
new file mode 100644
index 00000000..2ade2ba8
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field.h
@@ -0,0 +1,179 @@
+// 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_JAVA_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context);
+ ~ImmutableMessageFieldGenerator();
+
+ // implements ImmutableFieldGenerator
+ // ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ void PrintNestedBuilderCondition(io::Printer* printer,
+ const char* regular_case,
+ const char* nested_builder_case) const;
+ void PrintNestedBuilderFunction(io::Printer* printer,
+ const char* method_prototype,
+ const char* regular_case,
+ const char* nested_builder_case,
+ const char* trailing_code) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
+};
+
+class ImmutableMessageOneofFieldGenerator
+ : public ImmutableMessageFieldGenerator {
+ public:
+ ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ Context* context);
+ ~ImmutableMessageOneofFieldGenerator();
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
+};
+
+class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit RepeatedImmutableMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableMessageFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ void PrintNestedBuilderCondition(io::Printer* printer,
+ const char* regular_case,
+ const char* nested_builder_case) const;
+ void PrintNestedBuilderFunction(io::Printer* printer,
+ const char* method_prototype,
+ const char* regular_case,
+ const char* nested_builder_case,
+ const char* trailing_code) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.cc
new file mode 100644
index 00000000..f3050db3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.cc
@@ -0,0 +1,884 @@
+// 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 <compiler/java/java_message_field_lite.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ (*variables)["kt_type"] = (*variables)["type"];
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->message_type());
+ (*variables)["group_or_message"] =
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group"
+ : "Message";
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["required"] = descriptor->is_required() ? "true" : "false";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != null";
+ }
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+
+ // We use `x.getClass()` as a null check because it generates less bytecode
+ // than an `if (x == null) { throw ... }` statement.
+ (*variables)["null_check"] = "value.getClass();\n";
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableMessageFieldLiteGenerator::ImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : descriptor_(descriptor),
+ messageBitIndex_(messageBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ // TODO(dweis): We don't need a has bit for messages as they have null
+ // sentinels and no user should be reflecting on this. We could save some
+ // bits by setting to 0 and updating the runtimes but this might come at a
+ // runtime performance cost since we can't memoize has-bit reads.
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+
+ printer->Print(variables_, "private $type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (HasHasbit(descriptor_)) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $name$_ != null;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " $name$_ = value;\n"
+ " $set_has_field_bit_message$\n"
+ " }\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.SuppressWarnings({\"ReferenceEquality\"})\n"
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " if ($name$_ != null &&\n"
+ " $name$_ != $type$.getDefaultInstance()) {\n"
+ " $name$_ =\n"
+ " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {"
+ " $name$_ = null;\n"
+ " $clear_has_field_bit_message$\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ " }\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue.build());\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$merge$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ if (HasHasbit(descriptor_)) {
+ WriteIntToUtf16CharSequence(messageBitIndex_, output);
+ }
+ printer->Print(variables_, "\"$name$_\",\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {}
+
+std::string ImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldLiteGenerator::
+ ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context)
+ : ImmutableMessageFieldLiteGenerator(descriptor, messageBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldLiteGenerator::
+ ~ImmutableMessageOneofFieldLiteGenerator() {}
+
+void ImmutableMessageOneofFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " $oneof_name$_ = value;\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " if ($has_oneof_case_message$ &&\n"
+ " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+ " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+ " .mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $oneof_name$_ = value;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
+ printer->Print(variables_, "$oneof_stored_type$.class,\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue.build());\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$merge$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldLiteGenerator::
+ RepeatedImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableMessageFieldLiteGenerator::
+ ~RepeatedImmutableMessageFieldLiteGenerator() {}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having methods specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> \n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " ${$get$capitalized_name$OrBuilderList$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "${$get$capitalized_name$OrBuilder$}$(\n"
+ " int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ printer->Print(
+ variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ // Use a temporary to avoid a redundant iget-object.
+ " com.google.protobuf.Internal.ProtobufList<$type$> tmp = $name$_;\n"
+ " if (!tmp.isModifiable()) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " $null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " $null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " $null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, value);\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void remove$capitalized_name$(int index) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.remove(index);\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // repeated field of type "Field" called "RepeatedField".
+
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$type$> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index,\n"
+ " builderForValue.build());\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(builderForValue.build());\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index,\n"
+ " builderForValue.build());\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$remove$capitalized_name$$}$(int index) {\n"
+ " copyOnWrite();\n"
+ " instance.remove$capitalized_name$(index);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ printer->Print(variables_,
+ "\"$name$_\",\n"
+ "$type$.class,\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+std::string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.h
new file mode 100644
index 00000000..d34e61a5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_field_lite.h
@@ -0,0 +1,140 @@
+// 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_JAVA_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutableMessageFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator
+ // ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ const int messageBitIndex_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator);
+};
+
+class ImmutableMessageOneofFieldLiteGenerator
+ : public ImmutableMessageFieldLiteGenerator {
+ public:
+ ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutableMessageOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableMessageFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+ ~RepeatedImmutableMessageFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.cc
new file mode 100644
index 00000000..a8196c2d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.cc
@@ -0,0 +1,977 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_message_lite.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_enum_lite.h>
+#include <compiler/java/java_extension_lite.h>
+#include <compiler/java/java_generator_factory.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_message_builder.h>
+#include <compiler/java/java_message_builder_lite.h>
+#include <compiler/java/java_name_resolver.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+// ===================================================================
+ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : MessageGenerator(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A lite message generator is used to "
+ "generate non-lite messages.";
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (IsRealOneof(descriptor_->field(i))) {
+ oneofs_.insert(descriptor_->field(i)->containing_oneof());
+ }
+ }
+}
+
+ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
+
+void ImmutableMessageLiteGenerator::GenerateStaticVariables(
+ io::Printer* printer, int* bytecode_estimate) {
+ // Generate static members for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariables(printer, bytecode_estimate);
+ }
+}
+
+int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers(
+ io::Printer* printer) {
+ int bytecode_estimate = 0;
+ // Generate static member initializers for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ bytecode_estimate +=
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
+ }
+ return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+ /* immutable = */ true, "OrBuilder");
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessageLite.\n"
+ " ExtendableMessageOrBuilder<\n"
+ " $classname$, $classname$.Builder> {\n",
+ "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name(), "{", "", "}", "");
+ } else {
+ printer->Print(
+ "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageLiteOrBuilder {\n",
+ "deprecation",
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name(), "{", "", "}", "");
+ }
+ printer->Annotate("{", "}", descriptor_);
+
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInterfaceMembers(printer);
+ }
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
+ context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+ }
+ printer->Outdent();
+
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
+ bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
+
+ std::map<std::string, std::string> variables;
+ variables["static"] = is_own_file ? " " : " static ";
+ variables["classname"] = descriptor_->name();
+ variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+ variables["deprecation"] =
+ descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
+
+ WriteMessageDocComment(printer, descriptor_);
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+ /* immutable = */ true);
+
+
+ // The builder_type stores the super type name of the nested Builder class.
+ std::string builder_type;
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ variables,
+ "$deprecation$public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_));
+ } else {
+ printer->Print(
+ variables,
+ "$deprecation$public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+
+ builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
+ }
+ printer->Indent();
+
+ GenerateConstructor(printer);
+
+ // Nested types
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumLiteGenerator(descriptor_->enum_type(i), true, context_)
+ .Generate(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate Java classes for map entry messages.
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageLiteGenerator messageGenerator(descriptor_->nested_type(i),
+ context_);
+ messageGenerator.GenerateInterface(printer);
+ messageGenerator.Generate(printer);
+ }
+
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits +=
+ field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+
+ // oneof
+ std::map<std::string, std::string> vars;
+ for (auto oneof : oneofs_) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
+ vars["oneof_capitalized_name"] =
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
+ vars["oneof_index"] = StrCat((oneof)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // OneofCase enum
+ printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n");
+ printer->Indent();
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print("$field_name$($field_number$),\n", "field_name",
+ ToUpper(field->name()), "field_number",
+ StrCat(field->number()));
+ }
+ printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
+ ToUpper(vars["oneof_name"]));
+ printer->Print(vars,
+ "private final int value;\n"
+ "private $oneof_capitalized_name$Case(int value) {\n"
+ " this.value = value;\n"
+ "}\n");
+ printer->Print(
+ vars,
+ "/**\n"
+ " * @deprecated Use {@link #forNumber(int)} instead.\n"
+ " */\n"
+ "@java.lang.Deprecated\n"
+ "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+ " return forNumber(value);\n"
+ "}\n"
+ "\n"
+ "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
+ " switch (value) {\n");
+ for (int j = 0; j < (oneof)->field_count(); j++) {
+ const FieldDescriptor* field = (oneof)->field(j);
+ printer->Print(" case $field_number$: return $field_name$;\n",
+ "field_number", StrCat(field->number()),
+ "field_name", ToUpper(field->name()));
+ }
+ printer->Print(
+ " case 0: return $cap_oneof_name$_NOT_SET;\n"
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ // TODO(b/135620659): Rename this to "getFieldNumber" or something to
+ // disambiguate it from actual proto enums.
+ "public int getNumber() {\n"
+ " return this.value;\n"
+ "}\n",
+ "cap_oneof_name", ToUpper(vars["oneof_name"]));
+ printer->Outdent();
+ printer->Print("};\n\n");
+ // oneofCase()
+ printer->Print(vars,
+ "@java.lang.Override\n"
+ "public $oneof_capitalized_name$Case\n"
+ "get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "private void clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n"
+ "}\n"
+ "\n");
+ }
+
+ // Fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("public static final int $constant_name$ = $number$;\n",
+ "constant_name", FieldConstantName(descriptor_->field(i)),
+ "number", StrCat(descriptor_->field(i)->number()));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ GenerateParseFromMethods(printer);
+ GenerateBuilder(printer);
+
+ if (HasRequiredFields(descriptor_)) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). 0 means false, 1 means true, and all other values
+ // mean not yet computed.
+ printer->Print("private byte memoizedIsInitialized = 2;\n");
+ }
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n"
+ "protected final java.lang.Object dynamicMethod(\n"
+ " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+ " java.lang.Object arg0, java.lang.Object arg1) {\n"
+ " switch (method) {\n"
+ " case NEW_MUTABLE_INSTANCE: {\n"
+ " return new $classname$();\n"
+ " }\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+ printer->Indent();
+
+ printer->Print("case NEW_BUILDER: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodNewBuilder(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case BUILD_MESSAGE_INFO: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodNewBuildMessageInfo(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "// fall through\n"
+ "case GET_DEFAULT_INSTANCE: {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "case GET_PARSER: {\n"
+ // Generally one would use the lazy initialization holder pattern for
+ // manipulating static fields but that has exceptional cost on Android as
+ // it will generate an extra class for every message. Instead, use the
+ // double-check locking pattern which works just as well.
+ //
+ // The "parser" temporary mirrors the "PARSER" field to eliminate a read
+ // at the final return statement.
+ " com.google.protobuf.Parser<$classname$> parser = PARSER;\n"
+ " if (parser == null) {\n"
+ " synchronized ($classname$.class) {\n"
+ " parser = PARSER;\n"
+ " if (parser == null) {\n"
+ " parser =\n"
+ " new DefaultInstanceBasedParser<$classname$>(\n"
+ " DEFAULT_INSTANCE);\n"
+ " PARSER = parser;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return parser;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Outdent();
+
+ if (HasRequiredFields(descriptor_)) {
+ printer->Print(
+ "}\n"
+ "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return memoizedIsInitialized;\n"
+ "}\n"
+ "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+ " memoizedIsInitialized = (byte) (arg0 == null ? 0 : 1);\n"
+ " return null;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "}\n"
+ "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return (byte) 1;\n"
+ "}\n"
+ "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+ " return null;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ " throw new UnsupportedOperationException();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ // Carefully initialize the default instance in such a way that it doesn't
+ // conflict with other initialization.
+ printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
+ "classname",
+ name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "static {\n"
+ " $classname$ defaultInstance = new $classname$();\n"
+ " // New instances are implicitly immutable so no need to make\n"
+ " // immutable.\n"
+ " DEFAULT_INSTANCE = defaultInstance;\n"
+ // Register the default instance in a map. This map will be used by
+ // experimental runtime to lookup default instance given a class instance
+ // without using Java reflection.
+ " com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(\n"
+ " $classname$.class, defaultInstance);\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "public static $classname$ getDefaultInstance() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // 'of' method for Wrappers
+ if (IsWrappersProtoFile(descriptor_->file())) {
+ printer->Print(
+ "public static $classname$ of($field_type$ value) {\n"
+ " return newBuilder().setValue(value).build();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+ }
+
+ GenerateParser(printer);
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+ // the outer class's FileDescriptor.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
+ .Generate(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuildMessageInfo(
+ io::Printer* printer) {
+ printer->Indent();
+
+ // Collect field info into a sequence of UTF-16 chars. It will be embedded
+ // as a Java string in the generated code.
+ std::vector<uint16_t> chars;
+
+ int flags = 0;
+ if (IsProto2(descriptor_->file())) {
+ flags |= 0x1;
+ }
+ if (descriptor_->options().message_set_wire_format()) {
+ flags |= 0x2;
+ }
+ WriteIntToUtf16CharSequence(flags, &chars);
+ WriteIntToUtf16CharSequence(descriptor_->field_count(), &chars);
+
+ if (descriptor_->field_count() == 0) {
+ printer->Print("java.lang.Object[] objects = null;");
+ } else {
+ // A single array of all fields (including oneof, oneofCase, hasBits).
+ printer->Print("java.lang.Object[] objects = new java.lang.Object[] {\n");
+ printer->Indent();
+
+ // Record the number of oneofs.
+ WriteIntToUtf16CharSequence(oneofs_.size(), &chars);
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "\"$oneof_name$_\",\n"
+ "\"$oneof_name$Case_\",\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
+ }
+
+ // Integers for bit fields.
+ int total_bits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ total_bits +=
+ field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
+ }
+ int total_ints = (total_bits + 31) / 32;
+ for (int i = 0; i < total_ints; i++) {
+ printer->Print("\"$bit_field_name$\",\n", "bit_field_name",
+ GetBitFieldName(i));
+ }
+ WriteIntToUtf16CharSequence(total_ints, &chars);
+
+ int map_count = 0;
+ int repeated_count = 0;
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ if (field->is_map()) {
+ map_count++;
+ } else if (field->is_repeated()) {
+ repeated_count++;
+ }
+ }
+
+ WriteIntToUtf16CharSequence(sorted_fields[0]->number(), &chars);
+ WriteIntToUtf16CharSequence(
+ sorted_fields[descriptor_->field_count() - 1]->number(), &chars);
+ WriteIntToUtf16CharSequence(descriptor_->field_count(), &chars);
+ WriteIntToUtf16CharSequence(map_count, &chars);
+ WriteIntToUtf16CharSequence(repeated_count, &chars);
+
+ std::vector<const FieldDescriptor*> fields_for_is_initialized_check;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (descriptor_->field(i)->is_required() ||
+ (GetJavaType(descriptor_->field(i)) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(descriptor_->field(i)->message_type()))) {
+ fields_for_is_initialized_check.push_back(descriptor_->field(i));
+ }
+ }
+ WriteIntToUtf16CharSequence(fields_for_is_initialized_check.size(), &chars);
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ field_generators_.get(field).GenerateFieldInfo(printer, &chars);
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+ }
+
+ printer->Print("java.lang.String info =\n");
+ std::string line;
+ for (size_t i = 0; i < chars.size(); i++) {
+ uint16_t code = chars[i];
+ EscapeUtf16ToString(code, &line);
+ if (line.size() >= 80) {
+ printer->Print(" \"$string$\" +\n", "string", line);
+ line.clear();
+ }
+ }
+ printer->Print(" \"$string$\";\n", "string", line);
+
+ printer->Print("return newMessageInfo(DEFAULT_INSTANCE, info, objects);\n");
+ printer->Outdent();
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateParseFromMethods(
+ io::Printer* printer) {
+ printer->Print(
+ "public static $classname$ parseFrom(\n"
+ " java.nio.ByteBuffer data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " java.nio.ByteBuffer data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " byte[] data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, input, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(java.io.InputStream "
+ "input)\n"
+ " throws java.io.IOException {\n"
+ " return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return parseDelimitedFrom(DEFAULT_INSTANCE, input, "
+ "extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, input, extensionRegistry);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) {
+ printer->Print(
+ "public static Builder newBuilder() {\n"
+ " return (Builder) DEFAULT_INSTANCE.createBuilder();\n"
+ "}\n"
+ "public static Builder newBuilder($classname$ prototype) {\n"
+ " return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ MessageBuilderLiteGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
+ io::Printer* printer) {
+ printer->Print("return new Builder();\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateExtensionRegistrationCode(
+ io::Printer* printer) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
+ .GenerateRegistrationCode(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateExtensionRegistrationCode(printer);
+ }
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateConstructor(io::Printer* printer) {
+ printer->Print("private $classname$() {\n", "classname", descriptor_->name());
+ printer->Indent();
+
+ // Initialize all fields to default.
+ GenerateInitializers(printer);
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
+ printer->Print(
+ "private static volatile com.google.protobuf.Parser<$classname$> "
+ "PARSER;\n"
+ "\n"
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return DEFAULT_INSTANCE.getParserForType();\n"
+ "}\n",
+ "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!IsRealOneof(descriptor_->field(i))) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+}
+
+void ImmutableMessageLiteGenerator::GenerateKotlinDsl(
+ io::Printer* printer) const {
+ printer->Print(
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "@com.google.protobuf.kotlin.ProtoDslMarker\n");
+ printer->Print(
+ "public class Dsl private constructor(\n"
+ " private val _builder: $message$.Builder\n"
+ ") {\n"
+ " public companion object {\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @kotlin.PublishedApi\n"
+ " internal fun _create(builder: $message$.Builder): Dsl = "
+ "Dsl(builder)\n"
+ " }\n"
+ "\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " @kotlin.PublishedApi\n"
+ " internal fun _build(): $message$ = _builder.build()\n",
+ "message", name_resolver_->GetClassName(descriptor_, true));
+
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateKotlinDslMembers(printer);
+ }
+
+ for (auto oneof : oneofs_) {
+ printer->Print(
+ "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
+ " @JvmName(\"get$oneof_capitalized_name$Case\")\n"
+ " get() = _builder.get$oneof_capitalized_name$Case()\n\n"
+ "public fun clear$oneof_capitalized_name$() {\n"
+ " _builder.clear$oneof_capitalized_name$()\n"
+ "}\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
+ name_resolver_->GetClassName(descriptor_, true));
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ GenerateKotlinExtensions(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageLiteGenerator::GenerateKotlinMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
+ "kotlin.Unit): "
+ "$message$ =\n"
+ " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
+ "}._build()\n",
+ "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
+ "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
+ "message", name_resolver_->GetClassName(descriptor_, true));
+
+ printer->Print("public object $name$Kt {\n", "name", descriptor_->name());
+ printer->Indent();
+ GenerateKotlinDsl(printer);
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateKotlinMembers(printer);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
+ "kotlin.Unit): "
+ "$message$ =\n"
+ " $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
+ "}._build()\n",
+ "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
+ name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateTopLevelKotlinMembers(printer);
+ }
+}
+
+void ImmutableMessageLiteGenerator::GenerateKotlinExtensions(
+ io::Printer* printer) const {
+ std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+
+ printer->Print(
+ "@Suppress(\"UNCHECKED_CAST\")\n"
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun <T> get(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
+ " return if (extension.isRepeated) {\n"
+ " get(extension as com.google.protobuf.ExtensionLite<$message$, "
+ "List<*>>) as T\n"
+ " } else {\n"
+ " _builder.getExtension(extension)\n"
+ " }\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
+ "public operator fun <E> get(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+ "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
+ " return com.google.protobuf.kotlin.ExtensionList(extension, "
+ "_builder.getExtension(extension))\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun contains(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, *>): "
+ "Boolean {\n"
+ " return _builder.hasExtension(extension)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun clear(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, *>) "
+ "{\n"
+ " _builder.clearExtension(extension)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.PublishedApi\n"
+ "internal fun <T> setExtension(extension: "
+ "com.google.protobuf.ExtensionLite<$message$, T>, "
+ "value: T) {\n"
+ " _builder.setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <T : Comparable<T>> set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+ " value: T\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, "
+ "com.google.protobuf.ByteString>,\n"
+ " value: com.google.protobuf.ByteString\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
+ " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
+ " value: T\n"
+ ") {\n"
+ " setExtension(extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun<E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.add(value: E) {\n"
+ " _builder.addExtension(this.extension, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <E> "
+ "com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.plusAssign"
+ "(value: E) {\n"
+ " add(value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public fun<E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.addAll(values: Iterable<E>) {\n"
+ " for (value in values) {\n"
+ " add(value)\n"
+ " }\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun <E> "
+ "com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.plusAssign(values: "
+ "Iterable<E>) {\n"
+ " addAll(values)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "public operator fun <E> com.google.protobuf.kotlin.ExtensionList<E, "
+ "$message$>.set(index: Int, value: "
+ "E) {\n"
+ " _builder.setExtension(this.extension, index, value)\n"
+ "}\n\n",
+ "message", message_name);
+
+ printer->Print(
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline fun com.google.protobuf.kotlin.ExtensionList<*, "
+ "$message$>.clear() {\n"
+ " clear(extension)\n"
+ "}\n\n",
+ "message", message_name);
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.h
new file mode 100644
index 00000000..02f144bd
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_message_lite.h
@@ -0,0 +1,86 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+#include <compiler/java/java_message.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageLiteGenerator : public MessageGenerator {
+ public:
+ ImmutableMessageLiteGenerator(const Descriptor* descriptor, Context* context);
+ virtual ~ImmutableMessageLiteGenerator();
+
+ void Generate(io::Printer* printer) override;
+ void GenerateInterface(io::Printer* printer) override;
+ void GenerateExtensionRegistrationCode(io::Printer* printer) override;
+ void GenerateStaticVariables(io::Printer* printer,
+ int* bytecode_estimate) override;
+ int GenerateStaticVariableInitializers(io::Printer* printer) override;
+ void GenerateKotlinDsl(io::Printer* printer) const override;
+ void GenerateKotlinMembers(io::Printer* printer) const override;
+ void GenerateTopLevelKotlinMembers(io::Printer* printer) const override;
+
+ private:
+ void GenerateParseFromMethods(io::Printer* printer);
+
+ void GenerateBuilder(io::Printer* printer);
+ void GenerateDynamicMethodNewBuilder(io::Printer* printer);
+ void GenerateInitializers(io::Printer* printer);
+ void GenerateParser(io::Printer* printer);
+ void GenerateConstructor(io::Printer* printer);
+ void GenerateDynamicMethodNewBuildMessageInfo(io::Printer* printer);
+ void GenerateKotlinExtensions(io::Printer* printer) const;
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.cc
new file mode 100644
index 00000000..2d753bc5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.cc
@@ -0,0 +1,380 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <compiler/java/java_name_resolver.h>
+
+#include <map>
+#include <string>
+
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_names.h>
+#include <compiler/code_generator.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+// A suffix that will be appended to the file's outer class name if the name
+// conflicts with some other types defined in the file.
+const char* kOuterClassNameSuffix = "OuterClass";
+
+// Strip package name from a descriptor's full name.
+// For example:
+// Full name : foo.Bar.Baz
+// Package name: foo
+// After strip : Bar.Baz
+std::string StripPackageName(const std::string& full_name,
+ const FileDescriptor* file) {
+ if (file->package().empty()) {
+ return full_name;
+ } else {
+ // Strip package name
+ return full_name.substr(file->package().size() + 1);
+ }
+}
+
+// Get the name of a message's Java class without package name prefix.
+std::string ClassNameWithoutPackage(const Descriptor* descriptor,
+ bool immutable) {
+ return StripPackageName(descriptor->full_name(), descriptor->file());
+}
+
+std::string ClassNameWithoutPackageKotlin(const Descriptor* descriptor) {
+ std::string result = descriptor->name();
+ const Descriptor* temp = descriptor->containing_type();
+
+ while (temp) {
+ result = temp->name() + "Kt." + result;
+ temp = temp->containing_type();
+ }
+ return result;
+}
+
+// Get the name of an enum's Java class without package name prefix.
+std::string ClassNameWithoutPackage(const EnumDescriptor* descriptor,
+ bool immutable) {
+ // Doesn't append "Mutable" for enum type's name.
+ const Descriptor* message_descriptor = descriptor->containing_type();
+ if (message_descriptor == NULL) {
+ return descriptor->name();
+ } else {
+ return ClassNameWithoutPackage(message_descriptor, immutable) + "." +
+ descriptor->name();
+ }
+}
+
+// Get the name of a service's Java class without package name prefix.
+std::string ClassNameWithoutPackage(const ServiceDescriptor* descriptor,
+ bool immutable) {
+ std::string full_name =
+ StripPackageName(descriptor->full_name(), descriptor->file());
+ // We don't allow nested service definitions.
+ GOOGLE_CHECK(full_name.find('.') == std::string::npos);
+ return full_name;
+}
+
+// Return true if a and b are equals (case insensitive).
+NameEquality CheckNameEquality(const std::string& a, const std::string& b) {
+ if (ToUpper(a) == ToUpper(b)) {
+ if (a == b) {
+ return NameEquality::EXACT_EQUAL;
+ }
+ return NameEquality::EQUAL_IGNORE_CASE;
+ }
+ return NameEquality::NO_MATCH;
+}
+
+// Check whether a given message or its nested types has the given class name.
+bool MessageHasConflictingClassName(const Descriptor* message,
+ const std::string& classname,
+ NameEquality equality_mode) {
+ if (CheckNameEquality(message->name(), classname) == equality_mode) {
+ return true;
+ }
+ for (int i = 0; i < message->nested_type_count(); ++i) {
+ if (MessageHasConflictingClassName(message->nested_type(i), classname,
+ equality_mode)) {
+ return true;
+ }
+ }
+ for (int i = 0; i < message->enum_type_count(); ++i) {
+ if (CheckNameEquality(message->enum_type(i)->name(), classname) ==
+ equality_mode) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+ClassNameResolver::ClassNameResolver() {}
+
+ClassNameResolver::~ClassNameResolver() {}
+
+std::string ClassNameResolver::GetFileDefaultImmutableClassName(
+ const FileDescriptor* file) {
+ std::string basename;
+ std::string::size_type last_slash = file->name().find_last_of('/');
+ if (last_slash == std::string::npos) {
+ basename = file->name();
+ } else {
+ basename = file->name().substr(last_slash + 1);
+ }
+ return UnderscoresToCamelCase(StripProto(basename), true);
+}
+
+std::string ClassNameResolver::GetFileImmutableClassName(
+ const FileDescriptor* file) {
+ std::string& class_name = file_immutable_outer_class_names_[file];
+ if (class_name.empty()) {
+ if (file->options().has_java_outer_classname()) {
+ class_name = file->options().java_outer_classname();
+ } else {
+ class_name = GetFileDefaultImmutableClassName(file);
+ if (HasConflictingClassName(file, class_name,
+ NameEquality::EXACT_EQUAL)) {
+ class_name += kOuterClassNameSuffix;
+ }
+ }
+ }
+ return class_name;
+}
+
+std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file,
+ bool immutable) {
+ return GetFileClassName(file, immutable, false);
+}
+
+std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file,
+ bool immutable, bool kotlin) {
+ if (kotlin) {
+ return GetFileImmutableClassName(file) + "Kt";
+ } else if (immutable) {
+ return GetFileImmutableClassName(file);
+ } else {
+ return "Mutable" + GetFileImmutableClassName(file);
+ }
+}
+
+// Check whether there is any type defined in the proto file that has
+// the given class name.
+bool ClassNameResolver::HasConflictingClassName(const FileDescriptor* file,
+ const std::string& classname,
+ NameEquality equality_mode) {
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ if (CheckNameEquality(file->enum_type(i)->name(), classname) ==
+ equality_mode) {
+ return true;
+ }
+ }
+ for (int i = 0; i < file->service_count(); i++) {
+ if (CheckNameEquality(file->service(i)->name(), classname) ==
+ equality_mode) {
+ return true;
+ }
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (MessageHasConflictingClassName(file->message_type(i), classname,
+ equality_mode)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string ClassNameResolver::GetDescriptorClassName(
+ const FileDescriptor* descriptor) {
+ return GetFileImmutableClassName(descriptor);
+}
+
+std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
+ bool immutable) {
+ return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
+ bool immutable, bool kotlin) {
+ std::string result = FileJavaPackage(descriptor, immutable);
+ if (!result.empty()) result += '.';
+ result += GetFileClassName(descriptor, immutable, kotlin);
+ return result;
+}
+
+// Get the full name of a Java class by prepending the Java package name
+// or outer class name.
+std::string ClassNameResolver::GetClassFullName(
+ const std::string& name_without_package, const FileDescriptor* file,
+ bool immutable, bool is_own_file) {
+ return GetClassFullName(name_without_package, file, immutable, is_own_file,
+ false);
+}
+
+std::string ClassNameResolver::GetClassFullName(
+ const std::string& name_without_package, const FileDescriptor* file,
+ bool immutable, bool is_own_file, bool kotlin) {
+ std::string result;
+ if (is_own_file) {
+ result = FileJavaPackage(file, immutable);
+ } else {
+ result = GetClassName(file, immutable, kotlin);
+ }
+ if (!result.empty()) {
+ result += '.';
+ }
+ result += name_without_package;
+ if (kotlin) result += "Kt";
+ return result;
+}
+
+std::string ClassNameResolver::GetClassName(const Descriptor* descriptor,
+ bool immutable) {
+ return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const Descriptor* descriptor,
+ bool immutable, bool kotlin) {
+ return GetClassFullName(
+ ClassNameWithoutPackage(descriptor, immutable), descriptor->file(),
+ immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin);
+}
+
+std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor,
+ bool immutable) {
+ return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor,
+ bool immutable, bool kotlin) {
+ return GetClassFullName(
+ ClassNameWithoutPackage(descriptor, immutable), descriptor->file(),
+ immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin);
+}
+
+std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor,
+ bool immutable) {
+ return GetClassName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor,
+ bool immutable, bool kotlin) {
+ return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable),
+ descriptor->file(), immutable,
+ IsOwnFile(descriptor, immutable), kotlin);
+}
+
+// Get the Java Class style full name of a message.
+std::string ClassNameResolver::GetJavaClassFullName(
+ const std::string& name_without_package, const FileDescriptor* file,
+ bool immutable) {
+ return GetJavaClassFullName(name_without_package, file, immutable, false);
+}
+
+std::string ClassNameResolver::GetJavaClassFullName(
+ const std::string& name_without_package, const FileDescriptor* file,
+ bool immutable, bool kotlin) {
+ std::string result;
+ if (MultipleJavaFiles(file, immutable)) {
+ result = FileJavaPackage(file, immutable);
+ if (!result.empty()) result += '.';
+ } else {
+ result = GetClassName(file, immutable, kotlin);
+ if (!result.empty()) result += '$';
+ }
+ result += StringReplace(name_without_package, ".", "$", true);
+ return result;
+}
+
+std::string ClassNameResolver::GetExtensionIdentifierName(
+ const FieldDescriptor* descriptor, bool immutable) {
+ return GetExtensionIdentifierName(descriptor, immutable, false);
+}
+
+std::string ClassNameResolver::GetExtensionIdentifierName(
+ const FieldDescriptor* descriptor, bool immutable, bool kotlin) {
+ return GetClassName(descriptor->containing_type(), immutable, kotlin) + "." +
+ descriptor->name();
+}
+
+std::string ClassNameResolver::GetKotlinFactoryName(
+ const Descriptor* descriptor) {
+ std::string name = ToCamelCase(descriptor->name(), /* lower_first = */ true);
+ return IsForbiddenKotlin(name) ? name + "_" : name;
+}
+
+std::string ClassNameResolver::GetJavaImmutableClassName(
+ const Descriptor* descriptor) {
+ return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true),
+ descriptor->file(), true);
+}
+
+std::string ClassNameResolver::GetJavaImmutableClassName(
+ const EnumDescriptor* descriptor) {
+ return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true),
+ descriptor->file(), true);
+}
+
+std::string ClassNameResolver::GetKotlinExtensionsClassName(
+ const Descriptor* descriptor) {
+ return GetClassFullName(ClassNameWithoutPackageKotlin(descriptor),
+ descriptor->file(), true, true, true);
+}
+
+std::string ClassNameResolver::GetJavaMutableClassName(
+ const Descriptor* descriptor) {
+ return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false),
+ descriptor->file(), false);
+}
+
+std::string ClassNameResolver::GetJavaMutableClassName(
+ const EnumDescriptor* descriptor) {
+ return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false),
+ descriptor->file(), false);
+}
+
+std::string ClassNameResolver::GetDowngradedFileClassName(
+ const FileDescriptor* file) {
+ return "Downgraded" + GetFileClassName(file, false);
+}
+
+std::string ClassNameResolver::GetDowngradedClassName(
+ const Descriptor* descriptor) {
+ return FileJavaPackage(descriptor->file()) + "." +
+ GetDowngradedFileClassName(descriptor->file()) + "." +
+ ClassNameWithoutPackage(descriptor, false);
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.h
new file mode 100644
index 00000000..4d5a9bf6
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_name_resolver.h
@@ -0,0 +1,153 @@
+// 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_JAVA_NAME_RESOLVER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
+
+#include <map>
+#include <string>
+
+#include <stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class FileDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace java {
+
+// Indicates how closely the two class names match.
+enum NameEquality { NO_MATCH, EXACT_EQUAL, EQUAL_IGNORE_CASE };
+
+// Used to get the Java class related names for a given descriptor. It caches
+// the results to avoid redundant calculation across multiple name queries.
+// Thread-safety note: This class is *not* thread-safe.
+class ClassNameResolver {
+ public:
+ ClassNameResolver();
+ ~ClassNameResolver();
+
+ // Gets the unqualified outer class name for the file.
+ std::string GetFileClassName(const FileDescriptor* file, bool immutable);
+ std::string GetFileClassName(const FileDescriptor* file, bool immutable,
+ bool kotlin);
+ // Gets the unqualified immutable outer class name of a file.
+ std::string GetFileImmutableClassName(const FileDescriptor* file);
+ // Gets the unqualified default immutable outer class name of a file
+ // (converted from the proto file's name).
+ std::string GetFileDefaultImmutableClassName(const FileDescriptor* file);
+
+ // Check whether there is any type defined in the proto file that has
+ // the given class name.
+ bool HasConflictingClassName(const FileDescriptor* file,
+ const std::string& classname,
+ NameEquality equality_mode);
+
+ // Gets the name of the outer class that holds descriptor information.
+ // Descriptors are shared between immutable messages and mutable messages.
+ // Since both of them are generated optionally, the descriptors need to be
+ // put in another common place.
+ std::string GetDescriptorClassName(const FileDescriptor* file);
+
+ // Gets the fully-qualified class name corresponding to the given descriptor.
+ std::string GetClassName(const Descriptor* descriptor, bool immutable);
+ std::string GetClassName(const Descriptor* descriptor, bool immutable,
+ bool kotlin);
+ std::string GetClassName(const EnumDescriptor* descriptor, bool immutable);
+ std::string GetClassName(const EnumDescriptor* descriptor, bool immutable,
+ bool kotlin);
+ std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable);
+ std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable,
+ bool kotlin);
+ std::string GetClassName(const FileDescriptor* descriptor, bool immutable);
+ std::string GetClassName(const FileDescriptor* descriptor, bool immutable,
+ bool kotlin);
+
+ template <class DescriptorType>
+ std::string GetImmutableClassName(const DescriptorType* descriptor) {
+ return GetClassName(descriptor, true);
+ }
+ template <class DescriptorType>
+ std::string GetMutableClassName(const DescriptorType* descriptor) {
+ return GetClassName(descriptor, false);
+ }
+
+ // Gets the fully qualified name of an extension identifier.
+ std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor,
+ bool immutable);
+ std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor,
+ bool immutable, bool kotlin);
+
+ // Gets the fully qualified name for generated classes in Java convention.
+ // Nested classes will be separated using '$' instead of '.'
+ // For example:
+ // com.package.OuterClass$OuterMessage$InnerMessage
+ std::string GetJavaImmutableClassName(const Descriptor* descriptor);
+ std::string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
+ std::string GetKotlinFactoryName(const Descriptor* descriptor);
+ std::string GetKotlinExtensionsClassName(const Descriptor* descriptor);
+ std::string GetJavaMutableClassName(const Descriptor* descriptor);
+ std::string GetJavaMutableClassName(const EnumDescriptor* descriptor);
+ // Gets the outer class and the actual class for downgraded mutable messages.
+ std::string GetDowngradedFileClassName(const FileDescriptor* file);
+ std::string GetDowngradedClassName(const Descriptor* descriptor);
+
+ private:
+ // Get the full name of a Java class by prepending the Java package name
+ // or outer class name.
+ std::string GetClassFullName(const std::string& name_without_package,
+ const FileDescriptor* file, bool immutable,
+ bool is_own_file);
+ std::string GetClassFullName(const std::string& name_without_package,
+ const FileDescriptor* file, bool immutable,
+ bool is_own_file, bool kotlin);
+ // Get the Java Class style full name of a message.
+ std::string GetJavaClassFullName(const std::string& name_without_package,
+ const FileDescriptor* file, bool immutable);
+ std::string GetJavaClassFullName(const std::string& name_without_package,
+ const FileDescriptor* file, bool immutable,
+ bool kotlin);
+ // Caches the result to provide better performance.
+ std::map<const FileDescriptor*, std::string>
+ file_immutable_outer_class_names_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_names.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_names.h
new file mode 100644
index 00000000..313ace4f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_names.h
@@ -0,0 +1,100 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Provides a mechanism for mapping a descriptor to the
+// fully-qualified name of the corresponding Java class.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FileDescriptor;
+class FieldDescriptor;
+class ServiceDescriptor;
+
+namespace compiler {
+namespace java {
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified Java class name.
+std::string ClassName(const Descriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified Java class name.
+std::string ClassName(const EnumDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified Java class name.
+std::string ClassName(const FileDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// The fully-qualified Java class name.
+std::string ClassName(const ServiceDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+//
+// Returns:
+// Java package name.
+std::string FileJavaPackage(const FileDescriptor* descriptor);
+
+// Requires:
+// descriptor != NULL
+// Returns:
+// Capitalized camel case name field name.
+std::string CapitalizedFieldName(const FieldDescriptor* descriptor);
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_options.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_options.h
new file mode 100644
index 00000000..6c29be15
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_options.h
@@ -0,0 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generator options
+struct Options {
+ Options()
+ : generate_immutable_code(false),
+ generate_mutable_code(false),
+ generate_shared_code(false),
+ enforce_lite(false),
+ annotate_code(false) {
+ }
+
+ bool generate_immutable_code;
+ bool generate_mutable_code;
+ bool generate_shared_code;
+ // When set, the protoc will generate the current files and all the transitive
+ // dependencies as lite runtime.
+ bool enforce_lite;
+ // If true, we should build .meta files and emit @Generated annotations into
+ // generated code.
+ bool annotate_code;
+ // Name of a file where we will write a list of generated .meta file names,
+ // one per line.
+ std::string annotation_list_file;
+ // Name of a file where we will write a list of generated file names, one
+ // per line.
+ std::string output_list_file;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_plugin_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_plugin_unittest.cc
new file mode 100644
index 00000000..22ae3f24
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_plugin_unittest.cc
@@ -0,0 +1,119 @@
+// 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>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/java/java_generator.h>
+#include <compiler/command_line_interface.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+ TestGenerator() {}
+ ~TestGenerator() {}
+
+ virtual bool Generate(const FileDescriptor* file,
+ const std::string& parameter, GeneratorContext* context,
+ std::string* error) const {
+ std::string filename = "Test.java";
+ TryInsert(filename, "outer_class_scope", context);
+ TryInsert(filename, "class_scope:foo.Bar", context);
+ TryInsert(filename, "class_scope:foo.Bar.Baz", context);
+ TryInsert(filename, "builder_scope:foo.Bar", context);
+ TryInsert(filename, "builder_scope:foo.Bar.Baz", context);
+ TryInsert(filename, "enum_scope:foo.Qux", context);
+ return true;
+ }
+
+ void TryInsert(const std::string& filename,
+ const std::string& insertion_point,
+ GeneratorContext* context) const {
+ std::unique_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(JavaPluginTest, PluginTest) {
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "option java_package = \"\";\n"
+ "option java_outer_classname = \"Test\";\n"
+ "message Bar {\n"
+ " message Baz {}\n"
+ "}\n"
+ "enum Qux { BLAH = 1; }\n",
+ true));
+
+ CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ JavaGenerator java_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--java_out", &java_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ std::string proto_path = "-I" + TestTempDir();
+ std::string java_out = "--java_out=" + TestTempDir();
+ std::string test_out = "--test_out=" + TestTempDir();
+
+ const char* argv[] = {"protoc", proto_path.c_str(), java_out.c_str(),
+ test_out.c_str(), "test.proto"};
+
+ EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+} // namespace
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.cc
new file mode 100644
index 00000000..23d00b28
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.cc
@@ -0,0 +1,1111 @@
+// 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 <compiler/java/java_primitive_field.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+ JavaType javaType = GetJavaType(descriptor);
+
+ (*variables)["type"] = PrimitiveTypeName(javaType);
+ (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
+ (*variables)["kt_type"] = KotlinTypeName(javaType);
+ (*variables)["field_type"] = (*variables)["type"];
+
+ if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
+ javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
+ javaType == JAVATYPE_LONG) {
+ std::string capitalized_type = UnderscoresToCamelCase(
+ PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal." + capitalized_type + "List";
+ (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+ (*variables)["create_list"] = "new" + capitalized_type + "List()";
+ (*variables)["mutable_copy_list"] =
+ "mutableCopy(" + (*variables)["name"] + "_)";
+ (*variables)["name_make_immutable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_get"] =
+ (*variables)["name"] + "_.get" + capitalized_type;
+ (*variables)["repeated_add"] =
+ (*variables)["name"] + "_.add" + capitalized_type;
+ (*variables)["repeated_set"] =
+ (*variables)["name"] + "_.set" + capitalized_type;
+ } else {
+ (*variables)["field_list_type"] =
+ "java.util.List<" + (*variables)["boxed_type"] + ">";
+ (*variables)["create_list"] =
+ "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()";
+ (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" +
+ (*variables)["boxed_type"] + ">(" +
+ (*variables)["name"] + "_)";
+ (*variables)["empty_list"] = "java.util.Collections.emptyList()";
+ (*variables)["name_make_immutable"] =
+ (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" +
+ (*variables)["name"] + "_)";
+ (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
+ (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
+ (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+ }
+
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] =
+ IsDefaultValueJavaDefault(descriptor)
+ ? ""
+ : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
+ (*variables)["capitalized_type"] =
+ GetCapitalizedType(descriptor, /* immutable = */ true);
+ (*variables)["tag"] =
+ StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ if (IsReferenceType(GetJavaType(descriptor))) {
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ int fixed_size = FixedSize(GetType(descriptor));
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = StrCat(fixed_size);
+ }
+ (*variables)["on_changed"] = "onChanged();";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["set_has_field_bit_builder"] =
+ GenerateSetBit(builderBitIndex) + ";";
+ (*variables)["clear_has_field_bit_builder"] =
+ GenerateClearBit(builderBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_builder"] = "";
+ (*variables)["clear_has_field_bit_builder"] = "";
+
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_BYTES:
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["name"] + "_.isEmpty()";
+ break;
+ case FieldDescriptor::TYPE_FLOAT:
+ (*variables)["is_field_present_message"] =
+ "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] +
+ "_) != 0";
+ break;
+ case FieldDescriptor::TYPE_DOUBLE:
+ (*variables)["is_field_present_message"] =
+ "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] +
+ "_) != 0";
+ break;
+ default:
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"];
+ break;
+ }
+ }
+
+ // For repeated 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
+
+// ===================================================================
+
+ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
+
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+ return GetNumBitsForMessage();
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private $field_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_builder$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_builder$\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " $clear_has_field_bit_builder$\n");
+ printer->Annotate("{", "}", descriptor_);
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ printer->Print(
+ variables_,
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+ } else {
+ printer->Print(variables_, " $name$_ = $default$;\n");
+ }
+ printer->Print(variables_,
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ if (!IsDefaultValueJavaDefault(descriptor_)) {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+ }
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $default$;\n"
+ "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (other.get$capitalized_name$() != $default$) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ }
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ if (IsDefaultValueJavaDefault(descriptor_)) {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_from_local$) {\n"
+ " result.$name$_ = $name$_;\n"
+ " $set_has_field_bit_to_local$;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_from_local$) {\n"
+ " $set_has_field_bit_to_local$;\n"
+ "}\n"
+ "result.$name$_ = $name$_;\n");
+ }
+ } else {
+ printer->Print(variables_, "result.$name$_ = $name$_;\n");
+ }
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$set_has_field_bit_message$\n"
+ "$name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ // noop for primitives.
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$capitalized_type$($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "if (get$capitalized_name$()\n"
+ " != other.get$capitalized_name$()) return false;\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(
+ variables_,
+ "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
+ " != java.lang.Float.floatToIntBits(\n"
+ " other.get$capitalized_name$())) return false;\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(
+ variables_,
+ "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
+ " != java.lang.Double.doubleToLongBits(\n"
+ " other.get$capitalized_name$())) return false;\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(
+ variables_,
+ "if (!get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$())) return false;\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$();\n");
+ break;
+
+ case JAVATYPE_LONG:
+ printer->Print(
+ variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_BOOLEAN:
+ printer->Print(
+ variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(
+ variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(
+ variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
+ builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldGenerator::
+ ~ImmutablePrimitiveOneofFieldGenerator() {}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($boxed_type$) $oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($boxed_type$) $oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " $on_changed$\n"
+ " }\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " result.$oneof_name$_ = $oneof_name$_;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "set$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$oneof_name$_ = input.read$capitalized_type$();\n"
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$capitalized_type$(\n");
+ // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
+ // do redundant casts.
+ if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+ printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
+ }
+ printer->Print("}\n");
+}
+
+void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size(\n");
+ // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
+ // do redundant casts.
+ if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+ printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
+ }
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldGenerator::
+ RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldGenerator::
+ ~RepeatedImmutablePrimitiveFieldGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$boxed_type$> "
+ "get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private $field_list_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $repeated_get$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // One field is the list and the bit 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 reference 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.
+ printer->Print(variables_,
+ "private $field_list_type$ $name$_ = $empty_list$;\n");
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$get_mutable_bit_builder$) {\n"
+ " $name$_ = $mutable_copy_list$;\n"
+ " $set_mutable_bit_builder$;\n"
+ " }\n"
+ "}\n");
+
+ // 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.
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return $get_mutable_bit_builder$ ?\n"
+ " java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $repeated_get$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_set$(index, value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$$}$($type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_add$(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " $name$_ = $empty_list$;\n"
+ " $clear_mutable_bit_builder$;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::
+ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $empty_list$;\n"
+ "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::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 RepeatedImmutablePrimitiveFieldGenerator::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_make_immutable$;\n"
+ " $clear_mutable_bit_builder$;\n"
+ "}\n"
+ "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = $create_list$;\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
+ "$repeated_add$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCodeFromPacked(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = $create_list$;\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " $repeated_add$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name_make_immutable$; // C\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ if (descriptor_->is_packed()) {
+ // We invoke getSerializedSize in writeTo for messages that have packed
+ // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+ // That makes it safe to rely on the memoized size here.
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeUInt32NoTag($tag$);\n"
+ " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$NoTag($repeated_get$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$($number$, $repeated_get$(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ if (FixedSize(GetType(descriptor_)) == -1) {
+ printer->Print(
+ variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ printer->Print("size += dataSize;\n");
+
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->is_packed()) {
+ printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List())) return false;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.h
new file mode 100644
index 00000000..2291ecb2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field.h
@@ -0,0 +1,162 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context);
+ ~ImmutablePrimitiveFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator
+ // ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldGenerator
+ : public ImmutablePrimitiveFieldGenerator {
+ public:
+ ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveOneofFieldGenerator();
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldGenerator
+ : public ImmutableFieldGenerator {
+ public:
+ explicit RepeatedImmutablePrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutablePrimitiveFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.cc
new file mode 100644
index 00000000..7b680a70
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -0,0 +1,779 @@
+// 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 <compiler/java/java_primitive_field_lite.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+bool EnableExperimentalRuntimeForLite() {
+#ifdef PROTOBUF_EXPERIMENT
+ return PROTOBUF_EXPERIMENT;
+#else // PROTOBUF_EXPERIMENT
+ return false;
+#endif // !PROTOBUF_EXPERIMENT
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+ JavaType javaType = GetJavaType(descriptor);
+ (*variables)["type"] = PrimitiveTypeName(javaType);
+ (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
+ (*variables)["kt_type"] = KotlinTypeName(javaType);
+ (*variables)["field_type"] = (*variables)["type"];
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["capitalized_type"] =
+ GetCapitalizedType(descriptor, /* immutable = */ true);
+ (*variables)["tag"] =
+ StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ (*variables)["required"] = descriptor->is_required() ? "true" : "false";
+
+ std::string capitalized_type = UnderscoresToCamelCase(
+ PrimitiveTypeName(javaType), true /* cap_next_letter */);
+ switch (javaType) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_FLOAT:
+ case JAVATYPE_DOUBLE:
+ case JAVATYPE_BOOLEAN:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal." + capitalized_type + "List";
+ (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_get"] =
+ (*variables)["name"] + "_.get" + capitalized_type;
+ (*variables)["repeated_add"] =
+ (*variables)["name"] + "_.add" + capitalized_type;
+ (*variables)["repeated_set"] =
+ (*variables)["name"] + "_.set" + capitalized_type;
+ (*variables)["visit_type"] = capitalized_type;
+ (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
+ break;
+ default:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal.ProtobufList<" +
+ (*variables)["boxed_type"] + ">";
+ (*variables)["empty_list"] = "emptyProtobufList()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
+ (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
+ (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+ (*variables)["visit_type"] = "ByteString";
+ (*variables)["visit_type_list"] = "visitList";
+ }
+
+ if (javaType == JAVATYPE_BYTES) {
+ (*variables)["bytes_default"] =
+ ToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
+ }
+
+ if (IsReferenceType(javaType)) {
+ // We use `x.getClass()` as a null check because it generates less bytecode
+ // than an `if (x == null) { throw ... }` statement.
+ (*variables)["null_check"] =
+ " java.lang.Class<?> valueClass = value.getClass();\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ int fixed_size = FixedSize(GetType(descriptor));
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = StrCat(fixed_size);
+ }
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_BYTES:
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["name"] + "_.isEmpty()";
+ break;
+ case FieldDescriptor::TYPE_FLOAT:
+ (*variables)["is_field_present_message"] =
+ "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] +
+ "_) != 0";
+ break;
+ case FieldDescriptor::TYPE_DOUBLE:
+ (*variables)["is_field_present_message"] =
+ "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] +
+ "_) != 0";
+ break;
+ default:
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"];
+ break;
+ }
+ }
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutablePrimitiveFieldLiteGenerator::ImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : descriptor_(descriptor),
+ messageBitIndex_(messageBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ if (IsByteStringWithCustomDefaultValue(descriptor_)) {
+ // allocate this once statically since we know ByteStrings are immutable
+ // values that can be reused.
+ printer->Print(
+ variables_,
+ "private static final $field_type$ $bytes_default$ = $default$;\n");
+ }
+ printer->Print(variables_, "private $field_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n");
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ printer->Print(
+ variables_,
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+ } else {
+ printer->Print(variables_, " $name$_ = $default$;\n");
+ }
+ printer->Print(variables_, "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: $kt_type$\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ if (HasHasbit(descriptor_)) {
+ WriteIntToUtf16CharSequence(messageBitIndex_, output);
+ }
+ printer->Print(variables_, "\"$name$_\",\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ if (IsByteStringWithCustomDefaultValue(descriptor_)) {
+ printer->Print(variables_, "$name$_ = $bytes_default$;\n");
+ } else if (!IsDefaultValueJavaDefault(descriptor_)) {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+ }
+}
+
+std::string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+ ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context)
+ : ImmutablePrimitiveFieldLiteGenerator(descriptor, messageBitIndex,
+ context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+ ~ImmutablePrimitiveOneofFieldLiteGenerator() {}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($boxed_type$) $oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$set$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+ RepeatedImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ Context* context)
+ : descriptor_(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+ ~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$boxed_type$> "
+ "get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private $field_list_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return $repeated_get$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() &&
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+
+ printer->Print(
+ variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ // Use a temporary to avoid a redundant iget-object.
+ " $field_list_type$ tmp = $name$_;\n"
+ " if (!tmp.isModifiable()) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_set$(index, value);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_add$(value);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder "
+ "${$add$capitalized_name$$}$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$ public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: $kt_type$) {\n"
+ " add(value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
+ " addAll(values)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: $kt_type$) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ printer->Print(variables_, "\"$name$_\",\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+std::string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.h
new file mode 100644
index 00000000..8bfd7ae2
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_primitive_field_lite.h
@@ -0,0 +1,141 @@
+// 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_JAVA_PRIMITIVE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+ ~ImmutablePrimitiveFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator
+ // ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ const int messageBitIndex_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldLiteGenerator
+ : public ImmutablePrimitiveFieldLiteGenerator {
+ public:
+ ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutablePrimitiveOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+ ~RepeatedImmutablePrimitiveFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.cc
new file mode 100644
index 00000000..28407660
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.cc
@@ -0,0 +1,474 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_service.h>
+
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
+ : descriptor_(descriptor) {}
+
+ServiceGenerator::~ServiceGenerator() {}
+
+// ===================================================================
+ImmutableServiceGenerator::ImmutableServiceGenerator(
+ const ServiceDescriptor* descriptor, Context* context)
+ : ServiceGenerator(descriptor),
+ context_(context),
+ name_resolver_(context->GetNameResolver()) {}
+
+ImmutableServiceGenerator::~ImmutableServiceGenerator() {}
+
+void ImmutableServiceGenerator::Generate(io::Printer* printer) {
+ bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
+ WriteServiceDocComment(printer, descriptor_);
+ MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+ /* immutable = */ true);
+ printer->Print(
+ "public $static$ abstract class $classname$\n"
+ " implements com.google.protobuf.Service {\n",
+ "static", is_own_file ? "" : "static", "classname", descriptor_->name());
+ printer->Indent();
+
+ printer->Print("protected $classname$() {}\n\n", "classname",
+ descriptor_->name());
+
+ GenerateInterface(printer);
+
+ GenerateNewReflectiveServiceMethod(printer);
+ GenerateNewReflectiveBlockingServiceMethod(printer);
+
+ GenerateAbstractMethods(printer);
+
+ // Generate getDescriptor() and getDescriptorForType().
+ printer->Print(
+ "public static final\n"
+ " com.google.protobuf.Descriptors.ServiceDescriptor\n"
+ " getDescriptor() {\n"
+ " return $file$.getDescriptor().getServices().get($index$);\n"
+ "}\n",
+ "file", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "index", StrCat(descriptor_->index()));
+ GenerateGetDescriptorForType(printer);
+
+ // Generate more stuff.
+ GenerateCallMethod(printer);
+ GenerateGetPrototype(REQUEST, printer);
+ GenerateGetPrototype(RESPONSE, printer);
+ GenerateStub(printer);
+ GenerateBlockingStub(printer);
+
+ // Add an insertion point.
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateGetDescriptorForType(
+ io::Printer* printer) {
+ printer->Print(
+ "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
+ " getDescriptorForType() {\n"
+ " return getDescriptor();\n"
+ "}\n");
+}
+
+void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) {
+ printer->Print("public interface Interface {\n");
+ printer->Indent();
+ GenerateAbstractMethods(printer);
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.Service newReflectiveService(\n"
+ " final Interface impl) {\n"
+ " return new $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ printer->Print("@java.lang.Override\n");
+ GenerateMethodSignature(printer, method, IS_CONCRETE);
+ printer->Print(
+ " {\n"
+ " impl.$method$(controller, request, done);\n"
+ "}\n\n",
+ "method", UnderscoresToCamelCase(method));
+ }
+
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.BlockingService\n"
+ " newReflectiveBlockingService(final BlockingInterface impl) {\n"
+ " return new com.google.protobuf.BlockingService() {\n");
+ printer->Indent();
+ printer->Indent();
+
+ GenerateGetDescriptorForType(printer);
+
+ GenerateCallBlockingMethod(printer);
+ GenerateGetPrototype(REQUEST, printer);
+ GenerateGetPrototype(RESPONSE, printer);
+
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ WriteMethodDocComment(printer, method);
+ GenerateMethodSignature(printer, method, IS_ABSTRACT);
+ printer->Print(";\n\n");
+ }
+}
+
+std::string ImmutableServiceGenerator::GetOutput(
+ const MethodDescriptor* method) {
+ return name_resolver_->GetImmutableClassName(method->output_type());
+}
+
+void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
+ printer->Print(
+ "\n"
+ "public final void callMethod(\n"
+ " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " com.google.protobuf.Message request,\n"
+ " com.google.protobuf.RpcCallback<\n"
+ " com.google.protobuf.Message> done) {\n"
+ " if (method.getService() != getDescriptor()) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Service.callMethod() given method descriptor for wrong \" +\n"
+ " \"service type.\");\n"
+ " }\n"
+ " switch(method.getIndex()) {\n");
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ std::map<std::string, std::string> vars;
+ vars["index"] = StrCat(i);
+ vars["method"] = UnderscoresToCamelCase(method);
+ vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+ vars["output"] = GetOutput(method);
+ printer->Print(
+ vars,
+ "case $index$:\n"
+ " this.$method$(controller, ($input$)request,\n"
+ " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n"
+ " done));\n"
+ " return;\n");
+ }
+
+ printer->Print(
+ "default:\n"
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n"
+ "\n");
+}
+
+void ImmutableServiceGenerator::GenerateCallBlockingMethod(
+ io::Printer* printer) {
+ printer->Print(
+ "\n"
+ "public final com.google.protobuf.Message callBlockingMethod(\n"
+ " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " com.google.protobuf.Message request)\n"
+ " throws com.google.protobuf.ServiceException {\n"
+ " if (method.getService() != getDescriptor()) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Service.callBlockingMethod() given method descriptor for \" +\n"
+ " \"wrong service type.\");\n"
+ " }\n"
+ " switch(method.getIndex()) {\n");
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ std::map<std::string, std::string> vars;
+ vars["index"] = StrCat(i);
+ vars["method"] = UnderscoresToCamelCase(method);
+ vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+ vars["output"] = GetOutput(method);
+ printer->Print(vars,
+ "case $index$:\n"
+ " return impl.$method$(controller, ($input$)request);\n");
+ }
+
+ printer->Print(
+ "default:\n"
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n"
+ "\n");
+}
+
+void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
+ io::Printer* printer) {
+ /*
+ * TODO(cpovirk): The exception message says "Service.foo" when it may be
+ * "BlockingService.foo." Consider fixing.
+ */
+ printer->Print(
+ "public final com.google.protobuf.Message\n"
+ " get$request_or_response$Prototype(\n"
+ " com.google.protobuf.Descriptors.MethodDescriptor method) {\n"
+ " if (method.getService() != getDescriptor()) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Service.get$request_or_response$Prototype() given method \" +\n"
+ " \"descriptor for wrong service type.\");\n"
+ " }\n"
+ " switch(method.getIndex()) {\n",
+ "request_or_response", (which == REQUEST) ? "Request" : "Response");
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ std::map<std::string, std::string> vars;
+ vars["index"] = StrCat(i);
+ vars["type"] =
+ (which == REQUEST)
+ ? name_resolver_->GetImmutableClassName(method->input_type())
+ : GetOutput(method);
+ printer->Print(vars,
+ "case $index$:\n"
+ " return $type$.getDefaultInstance();\n");
+ }
+
+ printer->Print(
+ "default:\n"
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n"
+ "\n");
+}
+
+void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) {
+ printer->Print(
+ "public static Stub newStub(\n"
+ " com.google.protobuf.RpcChannel channel) {\n"
+ " return new Stub(channel);\n"
+ "}\n"
+ "\n"
+ "public static final class Stub extends $classname$ implements Interface "
+ "{"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Indent();
+
+ printer->Print(
+ "private Stub(com.google.protobuf.RpcChannel channel) {\n"
+ " this.channel = channel;\n"
+ "}\n"
+ "\n"
+ "private final com.google.protobuf.RpcChannel channel;\n"
+ "\n"
+ "public com.google.protobuf.RpcChannel getChannel() {\n"
+ " return channel;\n"
+ "}\n");
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ printer->Print("\n");
+ GenerateMethodSignature(printer, method, IS_CONCRETE);
+ printer->Print(" {\n");
+ printer->Indent();
+
+ std::map<std::string, std::string> vars;
+ vars["index"] = StrCat(i);
+ vars["output"] = GetOutput(method);
+ printer->Print(vars,
+ "channel.callMethod(\n"
+ " getDescriptor().getMethods().get($index$),\n"
+ " controller,\n"
+ " request,\n"
+ " $output$.getDefaultInstance(),\n"
+ " com.google.protobuf.RpcUtil.generalizeCallback(\n"
+ " done,\n"
+ " $output$.class,\n"
+ " $output$.getDefaultInstance()));\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
+ printer->Print(
+ "public static BlockingInterface newBlockingStub(\n"
+ " com.google.protobuf.BlockingRpcChannel channel) {\n"
+ " return new BlockingStub(channel);\n"
+ "}\n"
+ "\n");
+
+ printer->Print("public interface BlockingInterface {");
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ GenerateBlockingMethodSignature(printer, method);
+ printer->Print(";\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "private static final class BlockingStub implements BlockingInterface "
+ "{\n");
+ printer->Indent();
+
+ printer->Print(
+ "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
+ " this.channel = channel;\n"
+ "}\n"
+ "\n"
+ "private final com.google.protobuf.BlockingRpcChannel channel;\n");
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ GenerateBlockingMethodSignature(printer, method);
+ printer->Print(" {\n");
+ printer->Indent();
+
+ std::map<std::string, std::string> vars;
+ vars["index"] = StrCat(i);
+ vars["output"] = GetOutput(method);
+ printer->Print(vars,
+ "return ($output$) channel.callBlockingMethod(\n"
+ " getDescriptor().getMethods().get($index$),\n"
+ " controller,\n"
+ " request,\n"
+ " $output$.getDefaultInstance());\n");
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void ImmutableServiceGenerator::GenerateMethodSignature(
+ io::Printer* printer, const MethodDescriptor* method,
+ IsAbstract is_abstract) {
+ std::map<std::string, std::string> vars;
+ vars["name"] = UnderscoresToCamelCase(method);
+ vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+ vars["output"] = GetOutput(method);
+ vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
+ printer->Print(vars,
+ "public $abstract$ void $name$(\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " $input$ request,\n"
+ " com.google.protobuf.RpcCallback<$output$> done)");
+}
+
+void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
+ io::Printer* printer, const MethodDescriptor* method) {
+ std::map<std::string, std::string> vars;
+ vars["method"] = UnderscoresToCamelCase(method);
+ vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
+ vars["output"] = GetOutput(method);
+ printer->Print(vars,
+ "\n"
+ "public $output$ $method$(\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " $input$ request)\n"
+ " throws com.google.protobuf.ServiceException");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.h
new file mode 100644
index 00000000..f21d5f11
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_service.h
@@ -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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
+
+#include <map>
+#include <descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ServiceGenerator {
+ public:
+ explicit ServiceGenerator(const ServiceDescriptor* descriptor);
+ virtual ~ServiceGenerator();
+
+ virtual void Generate(io::Printer* printer) = 0;
+
+ enum RequestOrResponse { REQUEST, RESPONSE };
+ enum IsAbstract { IS_ABSTRACT, IS_CONCRETE };
+
+ protected:
+ const ServiceDescriptor* descriptor_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
+};
+
+class ImmutableServiceGenerator : public ServiceGenerator {
+ public:
+ ImmutableServiceGenerator(const ServiceDescriptor* descriptor,
+ Context* context);
+ virtual ~ImmutableServiceGenerator();
+
+ void Generate(io::Printer* printer) override;
+
+ private:
+ // Generate the getDescriptorForType() method.
+ void GenerateGetDescriptorForType(io::Printer* printer);
+
+ // Generate a Java interface for the service.
+ void GenerateInterface(io::Printer* printer);
+
+ // Generate newReflectiveService() method.
+ void GenerateNewReflectiveServiceMethod(io::Printer* printer);
+
+ // Generate newReflectiveBlockingService() method.
+ void GenerateNewReflectiveBlockingServiceMethod(io::Printer* printer);
+
+ // Generate abstract method declarations for all methods.
+ void GenerateAbstractMethods(io::Printer* printer);
+
+ // Generate the implementation of Service.callMethod().
+ void GenerateCallMethod(io::Printer* printer);
+
+ // Generate the implementation of BlockingService.callBlockingMethod().
+ void GenerateCallBlockingMethod(io::Printer* printer);
+
+ // Generate the implementations of Service.get{Request,Response}Prototype().
+ void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
+
+ // Generate a stub implementation of the service.
+ void GenerateStub(io::Printer* printer);
+
+ // Generate a method signature, possibly abstract, without body or trailing
+ // semicolon.
+ void GenerateMethodSignature(io::Printer* printer,
+ const MethodDescriptor* method,
+ IsAbstract is_abstract);
+
+ // Generate a blocking stub interface and implementation of the service.
+ void GenerateBlockingStub(io::Printer* printer);
+
+ // Generate the method signature for one method of a blocking stub.
+ void GenerateBlockingMethodSignature(io::Printer* printer,
+ const MethodDescriptor* method);
+
+ // Return the output type of the method.
+ std::string GetOutput(const MethodDescriptor* method);
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // NET_PROTO2_COMPILER_JAVA_SERVICE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.cc
new file mode 100644
index 00000000..935ce7bb
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.cc
@@ -0,0 +1,198 @@
+// 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: xiaofeng@google.com (Feng Xiao)
+
+#include <compiler/java/java_shared_code_generator.h>
+
+#include <memory>
+
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <compiler/java/java_names.h>
+#include <compiler/code_generator.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <descriptor.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file,
+ const Options& options)
+ : name_resolver_(new ClassNameResolver), file_(file), options_(options) {}
+
+SharedCodeGenerator::~SharedCodeGenerator() {}
+
+void SharedCodeGenerator::Generate(
+ GeneratorContext* context, std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_file_list) {
+ std::string java_package = FileJavaPackage(file_);
+ std::string package_dir = JavaPackageToDir(java_package);
+
+ if (HasDescriptorMethods(file_, options_.enforce_lite)) {
+ // Generate descriptors.
+ std::string classname = name_resolver_->GetDescriptorClassName(file_);
+ std::string filename = package_dir + classname + ".java";
+ file_list->push_back(filename);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ std::unique_ptr<io::Printer> printer(
+ new io::Printer(output.get(), '$',
+ options_.annotate_code ? &annotation_collector : NULL));
+ std::string info_relative_path = classname + ".java.pb.meta";
+ std::string info_full_path = filename + ".pb.meta";
+ 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);
+ }
+ PrintGeneratedAnnotation(printer.get(), '$',
+ options_.annotate_code ? info_relative_path : "");
+ printer->Print(
+ "public final class $classname$ {\n"
+ " public static com.google.protobuf.Descriptors.FileDescriptor\n"
+ " descriptor;\n"
+ " static {\n",
+ "classname", classname);
+ printer->Annotate("classname", file_->name());
+ printer->Indent();
+ printer->Indent();
+ GenerateDescriptors(printer.get());
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+
+ if (options_.annotate_code) {
+ std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+ context->Open(info_full_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ annotation_file_list->push_back(info_full_path);
+ }
+
+ printer.reset();
+ output.reset();
+ }
+}
+
+void SharedCodeGenerator::GenerateDescriptors(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);
+
+ std::string file_data;
+ file_proto.SerializeToString(&file_data);
+
+ printer->Print("java.lang.String[] descriptorData = {\n");
+ printer->Indent();
+
+ // Limit the number of bytes per line.
+ static const int kBytesPerLine = 40;
+ // Limit the number of lines per string part.
+ static const int kLinesPerPart = 400;
+ // Every block of bytes, start a new string literal, in order to avoid the
+ // 64k length limit. Note that this value needs to be <64k.
+ static const int kBytesPerPart = kBytesPerLine * kLinesPerPart;
+ for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+ if (i > 0) {
+ if (i % kBytesPerPart == 0) {
+ printer->Print(",\n");
+ } else {
+ printer->Print(" +\n");
+ }
+ }
+ printer->Print("\"$data$\"", "data",
+ CEscape(file_data.substr(i, kBytesPerLine)));
+ }
+
+ printer->Outdent();
+ printer->Print("\n};\n");
+
+ // -----------------------------------------------------------------
+ // Find out all dependencies.
+ std::vector<std::pair<std::string, std::string> > dependencies;
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ std::string filename = file_->dependency(i)->name();
+ std::string package = FileJavaPackage(file_->dependency(i));
+ std::string classname =
+ name_resolver_->GetDescriptorClassName(file_->dependency(i));
+ std::string full_name;
+ if (package.empty()) {
+ full_name = classname;
+ } else {
+ full_name = package + "." + classname;
+ }
+ dependencies.push_back(std::make_pair(filename, full_name));
+ }
+
+ // -----------------------------------------------------------------
+ // Invoke internalBuildGeneratedFileFrom() to build the file.
+ printer->Print(
+ "descriptor = com.google.protobuf.Descriptors.FileDescriptor\n"
+ " .internalBuildGeneratedFileFrom(descriptorData,\n");
+ printer->Print(
+ " new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
+
+ for (int i = 0; i < dependencies.size(); i++) {
+ const std::string& dependency = dependencies[i].second;
+ printer->Print(" $dependency$.getDescriptor(),\n", "dependency",
+ dependency);
+ }
+
+ printer->Print(" });\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.h
new file mode 100644
index 00000000..1e315863
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_shared_code_generator.h
@@ -0,0 +1,90 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: xiaofeng@google.com (Feng Xiao)
+//
+// Generators that generate shared code between immutable API and mutable API.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <stubs/common.h>
+#include <compiler/java/java_options.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor; // descriptor.h
+namespace compiler {
+class GeneratorContext; // code_generator.h
+namespace java {
+class ClassNameResolver; // name_resolver.h
+}
+} // namespace compiler
+namespace io {
+class Printer; // printer.h
+}
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// A generator that generates code that are shared between immutable API
+// and mutable API. Currently only descriptors are shared.
+class SharedCodeGenerator {
+ public:
+ SharedCodeGenerator(const FileDescriptor* file, const Options& options);
+ ~SharedCodeGenerator();
+
+ void Generate(GeneratorContext* generator_context,
+ std::vector<std::string>* file_list,
+ std::vector<std::string>* annotation_file_list);
+
+ void GenerateDescriptors(io::Printer* printer);
+
+ private:
+ std::unique_ptr<ClassNameResolver> name_resolver_;
+ const FileDescriptor* file_;
+ const Options options_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.cc
new file mode 100644
index 00000000..454148ca
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.cc
@@ -0,0 +1,1190 @@
+// 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)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_string_field.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
+
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] =
+ "= " + ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["capitalized_type"] = "String";
+ (*variables)["tag"] =
+ StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" +
+ GeneratedCodeVersionSuffix() +
+ ".isStringEmpty";
+ (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
+ GeneratedCodeVersionSuffix() + ".writeString";
+ (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
+ GeneratedCodeVersionSuffix() +
+ ".computeStringSize";
+
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["on_changed"] = "onChanged();";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["set_has_field_bit_builder"] =
+ GenerateSetBit(builderBitIndex) + ";";
+ (*variables)["clear_has_field_bit_builder"] =
+ GenerateClearBit(builderBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_builder"] = "";
+ (*variables)["clear_has_field_bit_builder"] = "";
+
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["isStringEmpty"] + "(" + (*variables)["name"] + "_)";
+ }
+
+ // For repeated 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
+
+// ===================================================================
+
+ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
+
+int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
+ return GetNumBitsForMessage();
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+// 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
+// strings, but rather fields that were raw bytes incorrectly marked
+// as strings in the proto file. This is common because in the proto1
+// syntax, string was the way to indicate bytes and C++ engineers can
+// easily make this mistake without affecting the C++ API. By converting to
+// strings immediately, some java code might corrupt these byte arrays as
+// it passes through a java server even if the field was never accessed by
+// application code.
+//
+// 2. There's a performance hit to converting between bytes and strings and
+// it many cases, the field is never even read by the application code. This
+// avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$();\n");
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " $name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8()) {\n"
+ " $name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " $name$_ = b;\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableStringFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "private java.lang.Object $name$_ $default_init$;\n");
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_builder$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (!(ref instanceof java.lang.String)) {\n"
+ " com.google.protobuf.ByteString bs =\n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " $name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8()) {\n"
+ " $name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " } else {\n"
+ " return (java.lang.String) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " $name$_ = b;\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_builder$\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " $clear_has_field_bit_builder$\n");
+ printer->Annotate("{", "}", descriptor_);
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ printer->Print(variables_,
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+ printer->Print(variables_,
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_has_field_bit_builder$\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: kotlin.String\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutableStringFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $default$;\n"
+ "$clear_has_field_bit_builder$\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ // Allow a slight breach of abstraction here in order to avoid forcing
+ // all string fields to Strings when copying fields from a Message.
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " $set_has_field_bit_builder$\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (!other.get$capitalized_name$().isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
+ "}\n");
+ }
+}
+
+void ImmutableStringFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_from_local$) {\n"
+ " $set_has_field_bit_to_local$;\n"
+ "}\n");
+ }
+ printer->Print(variables_, "result.$name$_ = $name$_;\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "java.lang.String s = input.readStringRequireUtf8();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ "com.google.protobuf.ByteString bs = input.readBytes();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ // noop for strings.
+}
+
+void ImmutableStringFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " $writeString$(output, $number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += $computeStringSize$($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$())) return false;\n");
+}
+
+void ImmutableStringFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+std::string ImmutableStringFieldGenerator::GetBoxedType() const {
+ return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
+ builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
+
+void ImmutableStringOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = b;\n"
+ " }\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (!(ref instanceof java.lang.String)) {\n"
+ " com.google.protobuf.ByteString bs =\n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n"
+ " if ($has_oneof_case_message$) {\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " $oneof_name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8()) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " }\n"
+ " return s;\n"
+ " } else {\n"
+ " return (java.lang.String) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = b;\n"
+ " }\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " $on_changed$\n"
+ " }\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ // Allow a slight breach of abstraction here in order to avoid forcing
+ // all string fields to Strings when copying fields from a Message.
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = other.$oneof_name$_;\n"
+ "$on_changed$\n");
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " result.$oneof_name$_ = $oneof_name$_;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "java.lang.String s = input.readStringRequireUtf8();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ "com.google.protobuf.ByteString bs = input.readBytes();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " $writeString$(output, $number$, $oneof_name$_);\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += $computeStringSize$($number$, $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldGenerator::
+ ~RepeatedImmutableStringFieldGenerator() {}
+
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ // NOTE: the same method in the implementation class actually returns
+ // com.google.protobuf.ProtocolStringList (a subclass of List). It's
+ // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
+ // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
+ // code, we make this interface method return List so both methods
+ // with different return types exist in the compiled byte code.
+ "$deprecation$java.util.List<java.lang.String>\n"
+ " get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index);\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.LazyStringList $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String "
+ "${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ // One field is the list and the bit 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 reference 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.
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
+
+ printer->Print(
+ variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$get_mutable_bit_builder$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+ " $set_mutable_bit_builder$;\n"
+ " }\n"
+ "}\n");
+
+ // 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.
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return $name$_.getUnmodifiableView();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String "
+ "${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " $name$_ = $empty_list$;\n"
+ " $clear_mutable_bit_builder$;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ // property for List<String>
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$kt_deprecation$public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.jvm.JvmSynthetic\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ // List<String>.add(String)
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: kotlin.String) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}\n");
+
+ // List<String> += String
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: kotlin.String) {\n"
+ " add(value)\n"
+ "}\n");
+
+ // List<String>.addAll(Iterable<String>)
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}\n");
+
+ // List<String> += Iterable<String>
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+ " addAll(values)\n"
+ "}\n");
+
+ // List<String>[Int] = String
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: kotlin.String) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+void RepeatedImmutableStringFieldGenerator::
+ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $empty_list$;\n"
+ "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::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 RepeatedImmutableStringFieldGenerator::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$_ = $name$_.getUnmodifiableView();\n"
+ " $clear_mutable_bit_builder$;\n"
+ "}\n"
+ "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateParsingCode(
+ io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "java.lang.String s = input.readStringRequireUtf8();\n");
+ } else {
+ printer->Print(variables_,
+ "com.google.protobuf.ByteString bs = input.readBytes();\n");
+ }
+ printer->Print(variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, "$name$_.add(s);\n");
+ } else {
+ printer->Print(variables_, "$name$_.add(bs);\n");
+ }
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateParsingDoneCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = $name$_.getUnmodifiableView();\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " $writeString$(output, $number$, $name$_.getRaw(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::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 += computeStringSizeNoTag($name$_.getRaw(i));\n"
+ "}\n");
+
+ printer->Print("size += dataSize;\n");
+
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List())) return false;\n");
+}
+
+void RepeatedImmutableStringFieldGenerator::GenerateHashCode(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
+ return "String";
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.h
new file mode 100644
index 00000000..03fd43ec
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field.h
@@ -0,0 +1,160 @@
+// 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)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringFieldGenerator();
+
+ // implements ImmutableFieldGenerator
+ // ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator);
+};
+
+class ImmutableStringOneofFieldGenerator
+ : public ImmutableStringFieldGenerator {
+ public:
+ ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ Context* context);
+ ~ImmutableStringOneofFieldGenerator();
+
+ private:
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator);
+};
+
+class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit RepeatedImmutableStringFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableStringFieldGenerator() override;
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const override;
+ int GetNumBitsForBuilder() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateBuilderClearCode(io::Printer* printer) const override;
+ void GenerateMergingCode(io::Printer* printer) const override;
+ void GenerateBuildingCode(io::Printer* printer) const override;
+ void GenerateParsingCode(io::Printer* printer) const override;
+ void GenerateParsingDoneCode(io::Printer* printer) const override;
+ void GenerateSerializationCode(io::Printer* printer) const override;
+ void GenerateSerializedSizeCode(io::Printer* printer) const override;
+ void GenerateFieldBuilderInitializationCode(
+ io::Printer* printer) const override;
+ void GenerateEqualsCode(io::Printer* printer) const override;
+ void GenerateHashCode(io::Printer* printer) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.cc b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.cc
new file mode 100644
index 00000000..6f52fd8f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.cc
@@ -0,0 +1,864 @@
+// 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)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <compiler/java/java_string_field_lite.h>
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/java/java_context.h>
+#include <compiler/java/java_doc_comment.h>
+#include <compiler/java/java_helpers.h>
+#include <compiler/java/java_name_resolver.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex, int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ std::map<std::string, std::string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["empty_list"] =
+ "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
+
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] =
+ "= " + ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["capitalized_type"] = "java.lang.String";
+ (*variables)["tag"] =
+ StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ // We use `x.getClass()` as a null check because it generates less bytecode
+ // than an `if (x == null) { throw ... }` statement.
+ (*variables)["null_check"] =
+ " java.lang.Class<?> valueClass = value.getClass();\n";
+
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] =
+ descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
+ (*variables)["kt_deprecation"] =
+ descriptor->options().deprecated()
+ ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
+ " is deprecated\") "
+ : "";
+ (*variables)["required"] = descriptor->is_required() ? "true" : "false";
+
+ if (HasHasbit(descriptor)) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["name"] + "_.isEmpty()";
+ }
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : descriptor_(descriptor),
+ messageBitIndex_(messageBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return HasHasbit(descriptor_) ? 1 : 0;
+}
+
+// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
+// strings are not stored as java.lang.String in the Message because of two
+// issues:
+//
+// 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
+// strings, but rather fields that were raw bytes incorrectly marked
+// as strings in the proto file. This is common because in the proto1
+// syntax, string was the way to indicate bytes and C++ engineers can
+// easily make this mistake without affecting the C++ API. By converting to
+// strings immediately, some java code might corrupt these byte arrays as
+// it passes through a java server even if the field was never accessed by
+// application code.
+//
+// 2. There's a performance hit to converting between bytes and strings and
+// it many cases, the field is never even read by the application code. This
+// avoids unnecessary conversions in the common use cases.
+//
+// In the LITE_RUNTIME, we store strings as java.lang.String because we assume
+// that the users of this runtime are not subject to proto1 constraints and are
+// running code on devices that are user facing. That is, the developers are
+// properly incentivized to only fetch the data they need to read and wish to
+// reduce the number of allocations incurred when running on a user's device.
+
+// TODO(dweis): Consider dropping all of the *Bytes() methods. They really
+// shouldn't be necessary or used on devices.
+void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$();\n");
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(variables_, "private java.lang.String $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " return $name$_;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ // The default value is not a simple literal so we want to
+ // avoid executing it multiple times. Instead, get the default
+ // out of the default instance.
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $name$_ = value.toStringUtf8();\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ }
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$kt_deprecation$public var $kt_name$: kotlin.String\n"
+ " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
+ " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
+ " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
+ " set(value) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
+ " }\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "public fun ${$clear$kt_capitalized_name$$}$() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}\n");
+
+ if (HasHazzer(descriptor_)) {
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(
+ variables_,
+ "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
+ " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
+ "}\n");
+ }
+}
+
+void ImmutableStringFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ if (HasHasbit(descriptor_)) {
+ WriteIntToUtf16CharSequence(messageBitIndex_, output);
+ }
+ printer->Print(variables_, "\"$name$_\",\n");
+}
+
+void ImmutableStringFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+std::string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldLiteGenerator::ImmutableStringOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
+ : ImmutableStringFieldLiteGenerator(descriptor, messageBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldLiteGenerator::
+ ~ImmutableStringOneofFieldLiteGenerator() {}
+
+void ImmutableStringOneofFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " java.lang.String ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
+ " }\n"
+ " return ref;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " java.lang.String ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
+ " }\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void ${$set$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void ${$clear$capitalized_name$$}$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER);
+ printer->Print(variables_,
+ "private void ${$set$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n");
+ printer->Annotate("{", "}", descriptor_);
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $oneof_name$_ = value.toStringUtf8();\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
+}
+
+void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ GOOGLE_DCHECK(HasHazzer(descriptor_));
+ WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldLiteGenerator::
+ RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context)
+ : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, 0,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldLiteGenerator::
+ ~RepeatedImmutableStringFieldLiteGenerator() {}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.String>\n"
+ " get$capitalized_name$List();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(
+ variables_,
+ "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index);\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.Internal.ProtobufList<java.lang.String> "
+ "$name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<java.lang.String> "
+ "${$get$capitalized_name$List$}$() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String "
+ "${$get$capitalized_name$$}$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$(int index) {\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " $name$_.get(index));\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ printer->Print(
+ variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ // Use a temporary to avoid a redundant iget-object.
+ " com.google.protobuf.Internal.ProtobufList<java.lang.String> tmp =\n"
+ " $name$_;"
+ " if (!tmp.isModifiable()) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value.toStringUtf8());\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
+ io::Printer* printer) const {
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.util.List<java.lang.String>\n"
+ " ${$get$capitalized_name$List$}$() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
+ printer->Print(
+ variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public java.lang.String "
+ "${$get$capitalized_name$$}$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+ LIST_INDEXED_GETTER);
+ printer->Print(variables_,
+ "@java.lang.Override\n"
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " ${$get$capitalized_name$Bytes$}$(int index) {\n"
+ " return instance.get$capitalized_name$Bytes(index);\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
+ " int index, java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ true);
+ printer->Print(variables_,
+ "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+
+ WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ true);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+ printer->Annotate("{", "}", descriptor_);
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * An uninstantiable, behaviorless type to represent the field in\n"
+ " * generics.\n"
+ " */\n"
+ "@kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
+ " : com.google.protobuf.kotlin.DslProxy()\n");
+
+ // property for List<String>
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+ printer->Print(
+ variables_,
+ "$kt_deprecation$public val $kt_name$: "
+ "com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
+ " @kotlin.OptIn"
+ "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
+ " get() = com.google.protobuf.kotlin.DslList(\n"
+ " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
+ " )\n");
+
+ // List<String>.add(String)
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "add(value: kotlin.String) {\n"
+ " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
+ "}\n");
+
+ // List<String> += String
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(value: kotlin.String) {\n"
+ " add(value)\n"
+ "}\n");
+
+ // List<String>.addAll(Iterable<String>)
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+ " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
+ "}\n");
+
+ // List<String> += Iterable<String>
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
+ "@Suppress(\"NOTHING_TO_INLINE\")\n"
+ "public inline operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
+ " addAll(values)\n"
+ "}\n");
+
+ // List<String>[Int] = String
+ WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
+ /* builder */ false);
+ printer->Print(
+ variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
+ "public operator fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "set(index: kotlin.Int, value: kotlin.String) {\n"
+ " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
+ "}");
+
+ WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
+ /* builder */ false);
+ printer->Print(variables_,
+ "@kotlin.jvm.JvmSynthetic\n"
+ "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
+ "public fun com.google.protobuf.kotlin.DslList"
+ "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
+ "clear() {\n"
+ " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
+ "}");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo(
+ io::Printer* printer, std::vector<uint16_t>* output) const {
+ WriteIntToUtf16CharSequence(descriptor_->number(), output);
+ WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
+ output);
+ printer->Print(variables_, "\"$name$_\",\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::GenerateInitializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+std::string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "java.lang.String";
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.h b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.h
new file mode 100644
index 00000000..880d41cc
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/java/java_string_field_lite.h
@@ -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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+
+#include <cstdint>
+#include <map>
+#include <string>
+
+#include <compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+class Context; // context.h
+class ClassNameResolver; // name_resolver.h
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ Context* context);
+ ~ImmutableStringFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator
+ // ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ const int messageBitIndex_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+};
+
+class ImmutableStringOneofFieldLiteGenerator
+ : public ImmutableStringFieldLiteGenerator {
+ public:
+ ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex, Context* context);
+ ~ImmutableStringOneofFieldLiteGenerator() override;
+
+ private:
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableStringFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+ ~RepeatedImmutableStringFieldLiteGenerator() override;
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ int GetNumBitsForMessage() const override;
+ void GenerateInterfaceMembers(io::Printer* printer) const override;
+ void GenerateMembers(io::Printer* printer) const override;
+ void GenerateBuilderMembers(io::Printer* printer) const override;
+ void GenerateInitializationCode(io::Printer* printer) const override;
+ void GenerateFieldInfo(io::Printer* printer,
+ std::vector<uint16_t>* output) const override;
+ void GenerateKotlinDslMembers(io::Printer* printer) const override;
+
+ std::string GetBoxedType() const override;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.cc
new file mode 100644
index 00000000..0a1fbb58
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.cc
@@ -0,0 +1,3941 @@
+// 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 <assert.h>
+#include <compiler/js/js_generator.h>
+#include <compiler/js/well_known_types_embed.h>
+#include <compiler/scc.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/common.h>
+#include <stubs/logging.h>
+#include <stubs/stringprintf.h>
+#include <stubs/strutil.h>
+
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace js {
+
+// Sorted list of JavaScript keywords. These cannot be used as names. If they
+// appear, we prefix them with "pb_".
+const char* kKeyword[] = {
+ "abstract", "boolean", "break", "byte", "case",
+ "catch", "char", "class", "const", "continue",
+ "debugger", "default", "delete", "do", "double",
+ "else", "enum", "export", "extends", "false",
+ "final", "finally", "float", "for", "function",
+ "goto", "if", "implements", "import", "in",
+ "instanceof", "int", "interface", "long", "native",
+ "new", "null", "package", "private", "protected",
+ "public", "return", "short", "static", "super",
+ "switch", "synchronized", "this", "throw", "throws",
+ "transient", "try", "typeof", "var", "void",
+ "volatile", "while", "with",
+};
+
+static const int kNumKeyword = sizeof(kKeyword) / sizeof(char*);
+
+namespace {
+
+// The mode of operation for bytes fields. Historically JSPB always carried
+// bytes as JS {string}, containing base64 content by convention. With binary
+// and proto3 serialization the new convention is to represent it as binary
+// data in Uint8Array. See b/26173701 for background on the migration.
+enum BytesMode {
+ BYTES_DEFAULT, // Default type for getBytesField to return.
+ BYTES_B64, // Explicitly coerce to base64 string where needed.
+ BYTES_U8, // Explicitly coerce to Uint8Array where needed.
+};
+
+bool IsReserved(const std::string& ident) {
+ for (int i = 0; i < kNumKeyword; i++) {
+ if (ident == kKeyword[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string GetSnakeFilename(const std::string& filename) {
+ std::string snake_name = filename;
+ ReplaceCharacters(&snake_name, "/", '_');
+ return snake_name;
+}
+
+// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
+// file foo/bar/baz.js.
+std::string GetJSFilename(const GeneratorOptions& options,
+ const std::string& filename) {
+ return StripProto(filename) + options.GetFileNameExtension();
+}
+
+// Given a filename like foo/bar/baz.proto, returns the root directory
+// path ../../
+std::string GetRootPath(const std::string& from_filename,
+ const std::string& to_filename) {
+ if (to_filename.find("google/protobuf") == 0) {
+ // Well-known types (.proto files in the google/protobuf directory) are
+ // assumed to come from the 'google-protobuf' npm package. We may want to
+ // generalize this exception later by letting others put generated code in
+ // their own npm packages.
+ return "google-protobuf/";
+ }
+
+ size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
+ if (slashes == 0) {
+ return "./";
+ }
+ std::string result = "";
+ for (size_t i = 0; i < slashes; i++) {
+ result += "../";
+ }
+ return result;
+}
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing.
+std::string ModuleAlias(const std::string& filename) {
+ // This scheme could technically cause problems if a file includes any 2 of:
+ // foo/bar_baz.proto
+ // foo_bar_baz.proto
+ // foo_bar/baz.proto
+ //
+ // We'll worry about this problem if/when we actually see it. This name isn't
+ // exposed to users so we can change it later if we need to.
+ std::string basename = StripProto(filename);
+ ReplaceCharacters(&basename, "-", '$');
+ ReplaceCharacters(&basename, "/", '_');
+ ReplaceCharacters(&basename, ".", '_');
+ return basename + "_pb";
+}
+
+// Returns the fully normalized JavaScript namespace for the given
+// file descriptor's package.
+std::string GetNamespace(const GeneratorOptions& options,
+ const FileDescriptor* file) {
+ if (!options.namespace_prefix.empty()) {
+ return options.namespace_prefix;
+ } else if (!file->package().empty()) {
+ return "proto." + file->package();
+ } else {
+ return "proto";
+ }
+}
+
+// Returns the name of the message with a leading dot and taking into account
+// nesting, for example ".OuterMessage.InnerMessage", or returns empty if
+// descriptor is null. This function does not handle namespacing, only message
+// nesting.
+std::string GetNestedMessageName(const Descriptor* descriptor) {
+ if (descriptor == NULL) {
+ return "";
+ }
+ std::string result =
+ StripPrefixString(descriptor->full_name(), descriptor->file()->package());
+ // Add a leading dot if one is not already present.
+ if (!result.empty() && result[0] != '.') {
+ result = "." + result;
+ }
+ return result;
+}
+
+// Returns the path prefix for a message or enumeration that
+// lives under the given file and containing type.
+std::string GetPrefix(const GeneratorOptions& options,
+ const FileDescriptor* file_descriptor,
+ const Descriptor* containing_type) {
+ std::string prefix = GetNamespace(options, file_descriptor) +
+ GetNestedMessageName(containing_type);
+ if (!prefix.empty()) {
+ prefix += ".";
+ }
+ return prefix;
+}
+
+// Returns the fully normalized JavaScript path prefix for the given
+// message descriptor.
+std::string GetMessagePathPrefix(const GeneratorOptions& options,
+ const Descriptor* descriptor) {
+ return GetPrefix(options, descriptor->file(), descriptor->containing_type());
+}
+
+// Returns the fully normalized JavaScript path for the given
+// message descriptor.
+std::string GetMessagePath(const GeneratorOptions& options,
+ const Descriptor* descriptor) {
+ return GetMessagePathPrefix(options, descriptor) + descriptor->name();
+}
+
+// Returns the fully normalized JavaScript path prefix for the given
+// enumeration descriptor.
+std::string GetEnumPathPrefix(const GeneratorOptions& options,
+ const EnumDescriptor* enum_descriptor) {
+ return GetPrefix(options, enum_descriptor->file(),
+ enum_descriptor->containing_type());
+}
+
+// Returns the fully normalized JavaScript path for the given
+// enumeration descriptor.
+std::string GetEnumPath(const GeneratorOptions& options,
+ const EnumDescriptor* enum_descriptor) {
+ return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name();
+}
+
+std::string MaybeCrossFileRef(const GeneratorOptions& options,
+ const FileDescriptor* from_file,
+ const Descriptor* to_message) {
+ if ((options.import_style == GeneratorOptions::kImportCommonJs ||
+ options.import_style == GeneratorOptions::kImportCommonJsStrict) &&
+ from_file != to_message->file()) {
+ // Cross-file ref in CommonJS needs to use the module alias instead of
+ // the global name.
+ return ModuleAlias(to_message->file()->name()) +
+ GetNestedMessageName(to_message->containing_type()) + "." +
+ to_message->name();
+ } else {
+ // Within a single file we use a full name.
+ return GetMessagePath(options, to_message);
+ }
+}
+
+std::string SubmessageTypeRef(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+ return MaybeCrossFileRef(options, field->file(), field->message_type());
+}
+
+// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields
+// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate,
+// and with reserved words triggering a "pb_" prefix.
+// - Getters/setters: LOWER_UNDERSCORE -> UPPER_CAMEL, except for group fields
+// (use the name directly), then append "List" if appropriate, then append "$"
+// if resulting name is equal to a reserved word.
+// - Enums: just uppercase.
+
+// Locale-independent version of ToLower that deals only with ASCII A-Z.
+char ToLowerASCII(char c) {
+ if (c >= 'A' && c <= 'Z') {
+ return (c - 'A') + 'a';
+ } else {
+ return c;
+ }
+}
+
+std::vector<std::string> ParseLowerUnderscore(const std::string& input) {
+ std::vector<std::string> words;
+ std::string running = "";
+ for (int i = 0; i < input.size(); i++) {
+ if (input[i] == '_') {
+ if (!running.empty()) {
+ words.push_back(running);
+ running.clear();
+ }
+ } else {
+ running += ToLowerASCII(input[i]);
+ }
+ }
+ if (!running.empty()) {
+ words.push_back(running);
+ }
+ return words;
+}
+
+std::vector<std::string> ParseUpperCamel(const std::string& input) {
+ std::vector<std::string> words;
+ std::string running = "";
+ for (int i = 0; i < input.size(); i++) {
+ if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) {
+ words.push_back(running);
+ running.clear();
+ }
+ running += ToLowerASCII(input[i]);
+ }
+ if (!running.empty()) {
+ words.push_back(running);
+ }
+ return words;
+}
+
+std::string ToLowerCamel(const std::vector<std::string>& words) {
+ std::string result;
+ for (int i = 0; i < words.size(); i++) {
+ std::string word = words[i];
+ if (i == 0 && (word[0] >= 'A' && word[0] <= 'Z')) {
+ word[0] = (word[0] - 'A') + 'a';
+ } else if (i != 0 && (word[0] >= 'a' && word[0] <= 'z')) {
+ word[0] = (word[0] - 'a') + 'A';
+ }
+ result += word;
+ }
+ return result;
+}
+
+std::string ToUpperCamel(const std::vector<std::string>& words) {
+ std::string result;
+ for (int i = 0; i < words.size(); i++) {
+ std::string word = words[i];
+ if (word[0] >= 'a' && word[0] <= 'z') {
+ word[0] = (word[0] - 'a') + 'A';
+ }
+ result += word;
+ }
+ return result;
+}
+
+// Based on code from descriptor.cc (Thanks Kenton!)
+// Uppercases the entire string, turning ValueName into
+// VALUENAME.
+std::string ToEnumCase(const std::string& input) {
+ std::string result;
+ result.reserve(input.size());
+
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ result.push_back(input[i] - 'a' + 'A');
+ } else {
+ result.push_back(input[i]);
+ }
+ }
+
+ return result;
+}
+
+std::string ToLower(const std::string& input) {
+ std::string result;
+ result.reserve(input.size());
+
+ for (int i = 0; i < input.size(); i++) {
+ if ('A' <= input[i] && input[i] <= 'Z') {
+ result.push_back(input[i] - 'A' + 'a');
+ } else {
+ result.push_back(input[i]);
+ }
+ }
+
+ return result;
+}
+
+// When we're generating one output file per SCC, this is the filename
+// that top-level extensions should go in.
+// e.g. one proto file (test.proto):
+// package a;
+// extends Foo {
+// ...
+// }
+// If "with_filename" equals true, the extension filename will be
+// "proto.a_test_extensions.js", otherwise will be "proto.a.js"
+std::string GetExtensionFileName(const GeneratorOptions& options,
+ const FileDescriptor* file,
+ bool with_filename) {
+ std::string snake_name = StripProto(GetSnakeFilename(file->name()));
+ return options.output_dir + "/" + ToLower(GetNamespace(options, file)) +
+ (with_filename ? ("_" + snake_name + "_extensions") : "") +
+ options.GetFileNameExtension();
+}
+// When we're generating one output file per SCC, this is the filename
+// that all messages in the SCC should go in.
+// If with_package equals true, filename will have package prefix,
+// If the filename length is longer than 200, the filename will be the
+// SCC's proto filename with suffix "_long_sccs_(index)" (if with_package equals
+// true it still has package prefix)
+std::string GetMessagesFileName(const GeneratorOptions& options, const SCC* scc,
+ bool with_package) {
+ static std::map<const Descriptor*, std::string>* long_name_dict =
+ new std::map<const Descriptor*, std::string>();
+ std::string package_base =
+ with_package
+ ? ToLower(GetNamespace(options, scc->GetRepresentative()->file()) +
+ "_")
+ : "";
+ std::string filename_base = "";
+ std::vector<std::string> all_message_names;
+ for (auto one_desc : scc->descriptors) {
+ if (one_desc->containing_type() == nullptr) {
+ all_message_names.push_back(ToLower(one_desc->name()));
+ }
+ }
+ sort(all_message_names.begin(), all_message_names.end());
+ for (auto one_message : all_message_names) {
+ if (!filename_base.empty()) {
+ filename_base += "_";
+ }
+ filename_base += one_message;
+ }
+ if (filename_base.size() + package_base.size() > 200) {
+ if ((*long_name_dict).find(scc->GetRepresentative()) ==
+ (*long_name_dict).end()) {
+ std::string snake_name = StripProto(
+ GetSnakeFilename(scc->GetRepresentative()->file()->name()));
+ (*long_name_dict)[scc->GetRepresentative()] =
+ StrCat(snake_name, "_long_sccs_",
+ static_cast<uint64>((*long_name_dict).size()));
+ }
+ filename_base = (*long_name_dict)[scc->GetRepresentative()];
+ }
+ return options.output_dir + "/" + package_base + filename_base +
+ options.GetFileNameExtension();
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level enum should go in.
+// If with_package equals true, filename will have package prefix.
+std::string GetEnumFileName(const GeneratorOptions& options,
+ const EnumDescriptor* desc, bool with_package) {
+ return options.output_dir + "/" +
+ (with_package ? ToLower(GetNamespace(options, desc->file()) + "_")
+ : "") +
+ ToLower(desc->name()) + options.GetFileNameExtension();
+}
+
+// Returns the message/response ID, if set.
+std::string GetMessageId(const Descriptor* desc) { return std::string(); }
+
+bool IgnoreExtensionField(const FieldDescriptor* field) {
+ // Exclude descriptor extensions from output "to avoid clutter" (from original
+ // codegen).
+ if (!field->is_extension()) return false;
+ const FileDescriptor* file = field->containing_type()->file();
+ return file->name() == "net/proto2/proto/descriptor.proto" ||
+ file->name() == "google/protobuf/descriptor.proto";
+}
+
+// Used inside Google only -- do not remove.
+bool IsResponse(const Descriptor* desc) { return false; }
+
+bool IgnoreField(const FieldDescriptor* field) {
+ return IgnoreExtensionField(field);
+}
+
+// Do we ignore this message type?
+bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); }
+
+// Does JSPB ignore this entire oneof? True only if all fields are ignored.
+bool IgnoreOneof(const OneofDescriptor* oneof) {
+ if (oneof->is_synthetic()) return true;
+ for (int i = 0; i < oneof->field_count(); i++) {
+ if (!IgnoreField(oneof->field(i))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string JSIdent(const GeneratorOptions& options,
+ const FieldDescriptor* field, bool is_upper_camel,
+ bool is_map, bool drop_list) {
+ std::string result;
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ result = is_upper_camel
+ ? ToUpperCamel(ParseUpperCamel(field->message_type()->name()))
+ : ToLowerCamel(ParseUpperCamel(field->message_type()->name()));
+ } else {
+ result = is_upper_camel ? ToUpperCamel(ParseLowerUnderscore(field->name()))
+ : ToLowerCamel(ParseLowerUnderscore(field->name()));
+ }
+ if (is_map || field->is_map()) {
+ // JSPB-style or proto3-style map.
+ result += "Map";
+ } else if (!drop_list && field->is_repeated()) {
+ // Repeated field.
+ result += "List";
+ }
+ return result;
+}
+
+std::string JSObjectFieldName(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ std::string name = JSIdent(options, field,
+ /* is_upper_camel = */ false,
+ /* is_map = */ false,
+ /* drop_list = */ false);
+ if (IsReserved(name)) {
+ name = "pb_" + name;
+ }
+ return name;
+}
+
+std::string JSByteGetterSuffix(BytesMode bytes_mode) {
+ switch (bytes_mode) {
+ case BYTES_DEFAULT:
+ return "";
+ case BYTES_B64:
+ return "B64";
+ case BYTES_U8:
+ return "U8";
+ default:
+ assert(false);
+ }
+ return "";
+}
+
+// Returns the field name as a capitalized portion of a getter/setter method
+// name, e.g. MyField for .getMyField().
+std::string JSGetterName(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ BytesMode bytes_mode = BYTES_DEFAULT,
+ bool drop_list = false) {
+ std::string name = JSIdent(options, field,
+ /* is_upper_camel = */ true,
+ /* is_map = */ false, drop_list);
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ std::string suffix = JSByteGetterSuffix(bytes_mode);
+ if (!suffix.empty()) {
+ name += "_as" + suffix;
+ }
+ }
+ if (name == "Extension" || name == "JsPbMessageId") {
+ // Avoid conflicts with base-class names.
+ name += "$";
+ }
+ return name;
+}
+
+std::string JSOneofName(const OneofDescriptor* oneof) {
+ return ToUpperCamel(ParseLowerUnderscore(oneof->name()));
+}
+
+// Returns the index corresponding to this field in the JSPB array (underlying
+// data storage array).
+std::string JSFieldIndex(const FieldDescriptor* field) {
+ // Determine whether this field is a member of a group. Group fields are a bit
+ // wonky: their "containing type" is a message type created just for the
+ // group, and that type's parent type has a field with the group-message type
+ // as its message type and TYPE_GROUP as its field type. For such fields, the
+ // index we use is relative to the field number of the group submessage field.
+ // For all other fields, we just use the field number.
+ const Descriptor* containing_type = field->containing_type();
+ const Descriptor* parent_type = containing_type->containing_type();
+ if (parent_type != NULL) {
+ for (int i = 0; i < parent_type->field_count(); i++) {
+ if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP &&
+ parent_type->field(i)->message_type() == containing_type) {
+ return StrCat(field->number() - parent_type->field(i)->number());
+ }
+ }
+ }
+ return StrCat(field->number());
+}
+
+std::string JSOneofIndex(const OneofDescriptor* oneof) {
+ int index = -1;
+ for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) {
+ const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i);
+ if (o->is_synthetic()) continue;
+ // If at least one field in this oneof is not JSPB-ignored, count the oneof.
+ for (int j = 0; j < o->field_count(); j++) {
+ const FieldDescriptor* f = o->field(j);
+ if (!IgnoreField(f)) {
+ index++;
+ break; // inner loop
+ }
+ }
+ if (o == oneof) {
+ break;
+ }
+ }
+ return StrCat(index);
+}
+
+// Decodes a codepoint in \x0000 -- \xFFFF.
+uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
+ if (*length == 0) {
+ return 0;
+ }
+ size_t expected = 0;
+ if ((*bytes & 0x80) == 0) {
+ expected = 1;
+ } else if ((*bytes & 0xe0) == 0xc0) {
+ expected = 2;
+ } else if ((*bytes & 0xf0) == 0xe0) {
+ expected = 3;
+ } else {
+ // Too long -- don't accept.
+ *length = 0;
+ return 0;
+ }
+
+ if (*length < expected) {
+ // Not enough bytes -- don't accept.
+ *length = 0;
+ return 0;
+ }
+
+ *length = expected;
+ switch (expected) {
+ case 1:
+ return bytes[0];
+ case 2:
+ return ((bytes[0] & 0x1F) << 6) | ((bytes[1] & 0x3F) << 0);
+ case 3:
+ return ((bytes[0] & 0x0F) << 12) | ((bytes[1] & 0x3F) << 6) |
+ ((bytes[2] & 0x3F) << 0);
+ default:
+ return 0;
+ }
+}
+
+// Escapes the contents of a string to be included within double-quotes ("") in
+// JavaScript. The input data should be a UTF-8 encoded C++ string of chars.
+// Returns false if |out| was truncated because |in| contained invalid UTF-8 or
+// codepoints outside the BMP.
+// TODO(b/115551870): Support codepoints outside the BMP.
+bool EscapeJSString(const std::string& in, std::string* out) {
+ size_t decoded = 0;
+ for (size_t i = 0; i < in.size(); i += decoded) {
+ uint16 codepoint = 0;
+ // Decode the next UTF-8 codepoint.
+ size_t have_bytes = in.size() - i;
+ uint8 bytes[3] = {
+ static_cast<uint8>(in[i]),
+ static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0),
+ static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0),
+ };
+ codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
+ if (have_bytes == 0) {
+ return false;
+ }
+ decoded = have_bytes;
+
+ switch (codepoint) {
+ case '\'':
+ *out += "\\x27";
+ break;
+ case '"':
+ *out += "\\x22";
+ break;
+ case '<':
+ *out += "\\x3c";
+ break;
+ case '=':
+ *out += "\\x3d";
+ break;
+ case '>':
+ *out += "\\x3e";
+ break;
+ case '&':
+ *out += "\\x26";
+ break;
+ case '\b':
+ *out += "\\b";
+ break;
+ case '\t':
+ *out += "\\t";
+ break;
+ case '\n':
+ *out += "\\n";
+ break;
+ case '\f':
+ *out += "\\f";
+ break;
+ case '\r':
+ *out += "\\r";
+ break;
+ case '\\':
+ *out += "\\\\";
+ break;
+ default:
+ // TODO(b/115551870): Once we're supporting codepoints outside the BMP,
+ // use a single Unicode codepoint escape if the output language is
+ // ECMAScript 2015 or above. Otherwise, use a surrogate pair.
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals
+ if (codepoint >= 0x20 && codepoint <= 0x7e) {
+ *out += static_cast<char>(codepoint);
+ } else if (codepoint >= 0x100) {
+ *out += StringPrintf("\\u%04x", codepoint);
+ } else {
+ *out += StringPrintf("\\x%02x", codepoint);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+std::string EscapeBase64(const std::string& in) {
+ static const char* kAlphabet =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ std::string result;
+
+ for (size_t i = 0; i < in.size(); i += 3) {
+ int value = (in[i] << 16) | (((i + 1) < in.size()) ? (in[i + 1] << 8) : 0) |
+ (((i + 2) < in.size()) ? (in[i + 2] << 0) : 0);
+ result += kAlphabet[(value >> 18) & 0x3f];
+ result += kAlphabet[(value >> 12) & 0x3f];
+ if ((i + 1) < in.size()) {
+ result += kAlphabet[(value >> 6) & 0x3f];
+ } else {
+ result += '=';
+ }
+ if ((i + 2) < in.size()) {
+ result += kAlphabet[(value >> 0) & 0x3f];
+ } else {
+ result += '=';
+ }
+ }
+
+ return result;
+}
+
+// Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the
+// original codegen's formatting (which is just .toString() on java.lang.Double
+// or java.lang.Float).
+std::string PostProcessFloat(std::string result) {
+ // If inf, -inf or nan, replace with +Infinity, -Infinity or NaN.
+ if (result == "inf") {
+ return "Infinity";
+ } else if (result == "-inf") {
+ return "-Infinity";
+ } else if (result == "nan") {
+ return "NaN";
+ }
+
+ // If scientific notation (e.g., "1e10"), (i) capitalize the "e", (ii)
+ // ensure that the mantissa (portion prior to the "e") has at least one
+ // fractional digit (after the decimal point), and (iii) strip any unnecessary
+ // leading zeroes and/or '+' signs from the exponent.
+ std::string::size_type exp_pos = result.find('e');
+ if (exp_pos != std::string::npos) {
+ std::string mantissa = result.substr(0, exp_pos);
+ std::string exponent = result.substr(exp_pos + 1);
+
+ // Add ".0" to mantissa if no fractional part exists.
+ if (mantissa.find('.') == std::string::npos) {
+ mantissa += ".0";
+ }
+
+ // Strip the sign off the exponent and store as |exp_neg|.
+ bool exp_neg = false;
+ if (!exponent.empty() && exponent[0] == '+') {
+ exponent = exponent.substr(1);
+ } else if (!exponent.empty() && exponent[0] == '-') {
+ exp_neg = true;
+ exponent = exponent.substr(1);
+ }
+
+ // Strip any leading zeroes off the exponent.
+ while (exponent.size() > 1 && exponent[0] == '0') {
+ exponent = exponent.substr(1);
+ }
+
+ return mantissa + "E" + std::string(exp_neg ? "-" : "") + exponent;
+ }
+
+ // Otherwise, this is an ordinary decimal number. Append ".0" if result has no
+ // decimal/fractional part in order to match output of original codegen.
+ if (result.find('.') == std::string::npos) {
+ result += ".0";
+ }
+
+ return result;
+}
+
+std::string FloatToString(float value) {
+ std::string result = SimpleFtoa(value);
+ return PostProcessFloat(result);
+}
+
+std::string DoubleToString(double value) {
+ std::string result = SimpleDtoa(value);
+ return PostProcessFloat(result);
+}
+
+bool InRealOneof(const FieldDescriptor* field) {
+ return field->containing_oneof() &&
+ !field->containing_oneof()->is_synthetic();
+}
+
+// Return true if this is an integral field that should be represented as string
+// in JS.
+bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ // The default value of JSType is JS_NORMAL, which behaves the same as
+ // JS_NUMBER.
+ return field->options().jstype() == FieldOptions::JS_STRING;
+ default:
+ return false;
+ }
+}
+
+std::string MaybeNumberString(const FieldDescriptor* field,
+ const std::string& orig) {
+ return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig;
+}
+
+std::string JSFieldDefault(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return "[]";
+ }
+
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return MaybeNumberString(field, StrCat(field->default_value_int32()));
+ case FieldDescriptor::CPPTYPE_UINT32:
+ // The original codegen is in Java, and Java protobufs store unsigned
+ // integer values as signed integer values. In order to exactly match the
+ // output, we need to reinterpret as base-2 signed. Ugh.
+ return MaybeNumberString(
+ field, StrCat(static_cast<int32>(field->default_value_uint32())));
+ case FieldDescriptor::CPPTYPE_INT64:
+ return MaybeNumberString(field, StrCat(field->default_value_int64()));
+ case FieldDescriptor::CPPTYPE_UINT64:
+ // See above note for uint32 -- reinterpreting as signed.
+ return MaybeNumberString(
+ field, StrCat(static_cast<int64>(field->default_value_uint64())));
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return StrCat(field->default_value_enum()->number());
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return FloatToString(field->default_value_float());
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return DoubleToString(field->default_value_double());
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (field->type() == FieldDescriptor::TYPE_STRING) {
+ std::string out;
+ bool is_valid = EscapeJSString(field->default_value_string(), &out);
+ if (!is_valid) {
+ // TODO(b/115551870): Decide whether this should be a hard error.
+ GOOGLE_LOG(WARNING)
+ << "The default value for field " << field->full_name()
+ << " was truncated since it contained invalid UTF-8 or"
+ " codepoints outside the basic multilingual plane.";
+ }
+ return "\"" + out + "\"";
+ } else { // Bytes
+ return "\"" + EscapeBase64(field->default_value_string()) + "\"";
+ }
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "null";
+ }
+ GOOGLE_LOG(FATAL) << "Shouldn't reach here.";
+ return "";
+}
+
+std::string ProtoTypeName(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_BOOL:
+ return "bool";
+ 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_STRING:
+ return "string";
+ case FieldDescriptor::TYPE_BYTES:
+ return "bytes";
+ case FieldDescriptor::TYPE_GROUP:
+ return GetMessagePath(options, field->message_type());
+ case FieldDescriptor::TYPE_ENUM:
+ return GetEnumPath(options, field->enum_type());
+ case FieldDescriptor::TYPE_MESSAGE:
+ return GetMessagePath(options, field->message_type());
+ default:
+ return "";
+ }
+}
+
+std::string JSIntegerTypeName(const FieldDescriptor* field) {
+ return IsIntegralFieldWithStringJSType(field) ? "string" : "number";
+}
+
+std::string JSStringTypeName(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ BytesMode bytes_mode) {
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ switch (bytes_mode) {
+ case BYTES_DEFAULT:
+ return "(string|Uint8Array)";
+ case BYTES_B64:
+ return "string";
+ case BYTES_U8:
+ return "Uint8Array";
+ default:
+ assert(false);
+ }
+ }
+ return "string";
+}
+
+std::string JSTypeName(const GeneratorOptions& options,
+ const FieldDescriptor* field, BytesMode bytes_mode) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "boolean";
+ case FieldDescriptor::CPPTYPE_INT32:
+ return JSIntegerTypeName(field);
+ case FieldDescriptor::CPPTYPE_INT64:
+ return JSIntegerTypeName(field);
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return JSIntegerTypeName(field);
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return JSIntegerTypeName(field);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "number";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "number";
+ case FieldDescriptor::CPPTYPE_STRING:
+ return JSStringTypeName(options, field, bytes_mode);
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return GetEnumPath(options, field->enum_type());
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return GetMessagePath(options, field->message_type());
+ default:
+ return "";
+ }
+}
+
+// Used inside Google only -- do not remove.
+bool UseBrokenPresenceSemantics(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ return false;
+}
+
+// Returns true for fields that return "null" from accessors when they are
+// unset. This should normally only be true for non-repeated submessages, but we
+// have legacy users who relied on old behavior where accessors behaved this
+// way.
+bool ReturnsNullWhenUnset(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ field->is_optional()) {
+ return true;
+ }
+
+ // TODO(haberman): remove this case and unconditionally return false.
+ return UseBrokenPresenceSemantics(options, field) && !field->is_repeated() &&
+ !field->has_default_value();
+}
+
+// In a sane world, this would be the same as ReturnsNullWhenUnset(). But in
+// the status quo, some fields declare that they never return null/undefined
+// even though they actually do:
+// * required fields
+// * optional enum fields
+// * proto3 primitive fields.
+bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->is_required() || field->type() == FieldDescriptor::TYPE_ENUM) {
+ return false;
+ }
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ return false;
+ }
+
+ return ReturnsNullWhenUnset(options, field);
+}
+
+bool SetterAcceptsUndefined(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (ReturnsNullWhenUnset(options, field)) {
+ return true;
+ }
+
+ // Broken presence semantics always accepts undefined for setters.
+ return UseBrokenPresenceSemantics(options, field);
+}
+
+bool SetterAcceptsNull(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (ReturnsNullWhenUnset(options, field)) {
+ return true;
+ }
+
+ // With broken presence semantics, fields with defaults accept "null" for
+ // setters, but other fields do not. This is a strange quirk of the old
+ // codegen.
+ return UseBrokenPresenceSemantics(options, field) &&
+ field->has_default_value();
+}
+
+// Returns types which are known to by non-nullable by default.
+// The style guide requires that we omit "!" in this case.
+bool IsPrimitive(const std::string& type) {
+ return type == "undefined" || type == "string" || type == "number" ||
+ type == "boolean";
+}
+
+std::string JSFieldTypeAnnotation(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ bool is_setter_argument, bool force_present,
+ bool singular_if_not_packed,
+ BytesMode bytes_mode = BYTES_DEFAULT,
+ bool force_singular = false) {
+ std::string jstype = JSTypeName(options, field, bytes_mode);
+
+ if (!force_singular && field->is_repeated() &&
+ (field->is_packed() || !singular_if_not_packed)) {
+ if (field->type() == FieldDescriptor::TYPE_BYTES &&
+ bytes_mode == BYTES_DEFAULT) {
+ jstype = "(Array<!Uint8Array>|Array<string>)";
+ } else {
+ if (!IsPrimitive(jstype)) {
+ jstype = "!" + jstype;
+ }
+ jstype = "Array<" + jstype + ">";
+ }
+ }
+
+ bool is_null_or_undefined = false;
+
+ if (is_setter_argument) {
+ if (SetterAcceptsNull(options, field)) {
+ jstype = "?" + jstype;
+ is_null_or_undefined = true;
+ }
+
+ if (SetterAcceptsUndefined(options, field)) {
+ jstype += "|undefined";
+ is_null_or_undefined = true;
+ }
+ } else if (force_present) {
+ // Don't add null or undefined.
+ } else {
+ if (DeclaredReturnTypeIsNullable(options, field)) {
+ jstype = "?" + jstype;
+ is_null_or_undefined = true;
+ }
+ }
+
+ if (!is_null_or_undefined && !IsPrimitive(jstype)) {
+ jstype = "!" + jstype;
+ }
+
+ return jstype;
+}
+
+std::string JSBinaryReaderMethodType(const FieldDescriptor* field) {
+ std::string name = field->type_name();
+ if (name[0] >= 'a' && name[0] <= 'z') {
+ name[0] = (name[0] - 'a') + 'A';
+ }
+ return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name;
+}
+
+std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
+ bool is_writer) {
+ std::string name = JSBinaryReaderMethodType(field);
+ if (field->is_packed()) {
+ name = "Packed" + name;
+ } else if (is_writer && field->is_repeated()) {
+ name = "Repeated" + name;
+ }
+ return name;
+}
+
+std::string JSBinaryReaderMethodName(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ return "jspb.BinaryReader.prototype.read" +
+ JSBinaryReadWriteMethodName(field, /* is_writer = */ false);
+}
+
+std::string JSBinaryWriterMethodName(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->containing_type() &&
+ field->containing_type()->options().message_set_wire_format()) {
+ return "jspb.BinaryWriter.prototype.writeMessageSet";
+ }
+ return "jspb.BinaryWriter.prototype.write" +
+ JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
+}
+
+std::string JSTypeTag(const FieldDescriptor* desc) {
+ switch (desc->type()) {
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ if (IsIntegralFieldWithStringJSType(desc)) {
+ return "StringInt";
+ } else {
+ return "Int";
+ }
+ case FieldDescriptor::TYPE_BOOL:
+ return "Boolean";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ default:
+ assert(false);
+ }
+ return "";
+}
+
+bool HasRepeatedFields(const GeneratorOptions& options,
+ const Descriptor* desc) {
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static const char* kRepeatedFieldArrayName = ".repeatedFields_";
+
+std::string RepeatedFieldsArrayName(const GeneratorOptions& options,
+ const Descriptor* desc) {
+ return HasRepeatedFields(options, desc)
+ ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName)
+ : "null";
+}
+
+bool HasOneofFields(const Descriptor* desc) {
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (InRealOneof(desc->field(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static const char* kOneofGroupArrayName = ".oneofGroups_";
+
+std::string OneofFieldsArrayName(const GeneratorOptions& options,
+ const Descriptor* desc) {
+ return HasOneofFields(desc)
+ ? (GetMessagePath(options, desc) + kOneofGroupArrayName)
+ : "null";
+}
+
+std::string RepeatedFieldNumberList(const GeneratorOptions& options,
+ const Descriptor* desc) {
+ std::vector<std::string> numbers;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) {
+ numbers.push_back(JSFieldIndex(desc->field(i)));
+ }
+ }
+ return "[" + Join(numbers, ",") + "]";
+}
+
+std::string OneofGroupList(const Descriptor* desc) {
+ // List of arrays (one per oneof), each of which is a list of field indices
+ std::vector<std::string> oneof_entries;
+ for (int i = 0; i < desc->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = desc->oneof_decl(i);
+ if (IgnoreOneof(oneof)) {
+ continue;
+ }
+
+ std::vector<std::string> oneof_fields;
+ for (int j = 0; j < oneof->field_count(); j++) {
+ if (IgnoreField(oneof->field(j))) {
+ continue;
+ }
+ oneof_fields.push_back(JSFieldIndex(oneof->field(j)));
+ }
+ oneof_entries.push_back("[" + Join(oneof_fields, ",") + "]");
+ }
+ return "[" + Join(oneof_entries, ",") + "]";
+}
+
+std::string JSOneofArray(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ return OneofFieldsArrayName(options, field->containing_type()) + "[" +
+ JSOneofIndex(field->containing_oneof()) + "]";
+}
+
+std::string RelativeTypeName(const FieldDescriptor* field) {
+ assert(field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+ // For a field with an enum or message type, compute a name relative to the
+ // path name of the message type containing this field.
+ std::string package = field->file()->package();
+ std::string containing_type = field->containing_type()->full_name() + ".";
+ std::string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM)
+ ? field->enum_type()->full_name()
+ : field->message_type()->full_name();
+
+ // |prefix| is advanced as we find separators '.' past the common package
+ // prefix that yield common prefixes in the containing type's name and this
+ // type's name.
+ int prefix = 0;
+ for (int i = 0; i < type.size() && i < containing_type.size(); i++) {
+ if (type[i] != containing_type[i]) {
+ break;
+ }
+ if (type[i] == '.' && i >= package.size()) {
+ prefix = i + 1;
+ }
+ }
+
+ return type.substr(prefix);
+}
+
+std::string JSExtensionsObjectName(const GeneratorOptions& options,
+ const FileDescriptor* from_file,
+ const Descriptor* desc) {
+ if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
+ // TODO(haberman): fix this for the kImportCommonJs case.
+ return "jspb.Message.messageSetExtensions";
+ } else {
+ return MaybeCrossFileRef(options, from_file, desc) + ".extensions";
+ }
+}
+
+static const int kMapKeyField = 1;
+static const int kMapValueField = 2;
+
+const FieldDescriptor* MapFieldKey(const FieldDescriptor* field) {
+ assert(field->is_map());
+ return field->message_type()->FindFieldByNumber(kMapKeyField);
+}
+
+const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) {
+ assert(field->is_map());
+ return field->message_type()->FindFieldByNumber(kMapValueField);
+}
+
+std::string FieldDefinition(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ std::string key_type = ProtoTypeName(options, key_field);
+ std::string value_type;
+ if (value_field->type() == FieldDescriptor::TYPE_ENUM ||
+ value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ value_type = RelativeTypeName(value_field);
+ } else {
+ value_type = ProtoTypeName(options, value_field);
+ }
+ return StringPrintf("map<%s, %s> %s = %d;", key_type.c_str(),
+ value_type.c_str(), field->name().c_str(),
+ field->number());
+ } else {
+ std::string qualifier =
+ field->is_repeated() ? "repeated"
+ : (field->is_optional() ? "optional" : "required");
+ std::string type, name;
+ if (field->type() == FieldDescriptor::TYPE_ENUM ||
+ field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ type = RelativeTypeName(field);
+ name = field->name();
+ } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ type = "group";
+ name = field->message_type()->name();
+ } else {
+ type = ProtoTypeName(options, field);
+ name = field->name();
+ }
+ return StringPrintf("%s %s %s = %d;", qualifier.c_str(), type.c_str(),
+ name.c_str(), field->number());
+ }
+}
+
+std::string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
+ std::string comments;
+ if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
+ comments +=
+ " * Note that Uint8Array is not supported on all browsers.\n"
+ " * @see http://caniuse.com/Uint8Array\n";
+ }
+ return comments;
+}
+
+bool ShouldGenerateExtension(const FieldDescriptor* field) {
+ return field->is_extension() && !IgnoreField(field);
+}
+
+bool HasExtensions(const Descriptor* desc) {
+ for (int i = 0; i < desc->extension_count(); i++) {
+ if (ShouldGenerateExtension(desc->extension(i))) {
+ return true;
+ }
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ if (HasExtensions(desc->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool HasExtensions(const FileDescriptor* file) {
+ for (int i = 0; i < file->extension_count(); i++) {
+ if (ShouldGenerateExtension(file->extension(i))) {
+ return true;
+ }
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (HasExtensions(file->message_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool HasMap(const GeneratorOptions& options, const Descriptor* desc) {
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (desc->field(i)->is_map()) {
+ return true;
+ }
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ if (HasMap(options, desc->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool FileHasMap(const GeneratorOptions& options, const FileDescriptor* desc) {
+ for (int i = 0; i < desc->message_type_count(); i++) {
+ if (HasMap(options, desc->message_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsExtendable(const Descriptor* desc) {
+ return desc->extension_range_count() > 0;
+}
+
+// Returns the max index in the underlying data storage array beyond which the
+// extension object is used.
+std::string GetPivot(const Descriptor* desc) {
+ static const int kDefaultPivot = 500;
+
+ // Find the max field number
+ int max_field_number = 0;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (!IgnoreField(desc->field(i)) &&
+ desc->field(i)->number() > max_field_number) {
+ max_field_number = desc->field(i)->number();
+ }
+ }
+
+ int pivot = -1;
+ if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) {
+ pivot = ((max_field_number + 1) < kDefaultPivot) ? (max_field_number + 1)
+ : kDefaultPivot;
+ }
+
+ return StrCat(pivot);
+}
+
+// Whether this field represents presence. For fields with presence, we
+// generate extra methods (clearFoo() and hasFoo()) for this field.
+bool HasFieldPresence(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ // This returns false for repeated fields and maps, but we still do
+ // generate clearFoo() methods for these through a special case elsewhere.
+ return field->has_presence();
+}
+
+// We use this to implement the semantics that same file can be generated
+// multiple times, but only the last one keep the short name. Others all use
+// long name with extra information to distinguish (For message and enum, the
+// extra information is package name, for file level extension, the extra
+// information is proto's filename).
+// We never actually write the files, but we keep a set of which descriptors
+// were the final one for a given filename.
+class FileDeduplicator {
+ public:
+ explicit FileDeduplicator(const GeneratorOptions& options) {}
+
+ // params:
+ // filenames: a pair of {short filename, full filename}
+ // (short filename don't have extra information, full filename
+ // contains extra information)
+ // desc: The Descriptor or SCC pointer or EnumDescriptor.
+ bool AddFile(const std::pair<std::string, std::string> filenames,
+ const void* desc) {
+ if (descs_by_shortname_.find(filenames.first) !=
+ descs_by_shortname_.end()) {
+ // Change old pointer's actual name to full name.
+ auto short_name_desc = descs_by_shortname_[filenames.first];
+ allowed_descs_actual_name_[short_name_desc] =
+ allowed_descs_full_name_[short_name_desc];
+ }
+ descs_by_shortname_[filenames.first] = desc;
+ allowed_descs_actual_name_[desc] = filenames.first;
+ allowed_descs_full_name_[desc] = filenames.second;
+
+ return true;
+ }
+
+ void GetAllowedMap(std::map<const void*, std::string>* allowed_set) {
+ *allowed_set = allowed_descs_actual_name_;
+ }
+
+ private:
+ // The map that restores all the descs that are using short name as filename.
+ std::map<std::string, const void*> descs_by_shortname_;
+ // The final actual filename map.
+ std::map<const void*, std::string> allowed_descs_actual_name_;
+ // The full name map.
+ std::map<const void*, std::string> allowed_descs_full_name_;
+};
+
+void DepthFirstSearch(const FileDescriptor* file,
+ std::vector<const FileDescriptor*>* list,
+ std::set<const FileDescriptor*>* seen) {
+ if (!seen->insert(file).second) {
+ return;
+ }
+
+ // Add all dependencies.
+ for (int i = 0; i < file->dependency_count(); i++) {
+ DepthFirstSearch(file->dependency(i), list, seen);
+ }
+
+ // Add this file.
+ list->push_back(file);
+}
+
+// A functor for the predicate to remove_if() below. Returns true if a given
+// FileDescriptor is not in the given set.
+class NotInSet {
+ public:
+ explicit NotInSet(const std::set<const FileDescriptor*>& file_set)
+ : file_set_(file_set) {}
+
+ bool operator()(const FileDescriptor* file) {
+ return file_set_.count(file) == 0;
+ }
+
+ private:
+ const std::set<const FileDescriptor*>& file_set_;
+};
+
+// This function generates an ordering of the input FileDescriptors that matches
+// the logic of the old code generator. The order is significant because two
+// different input files can generate the same output file, and the last one
+// needs to win.
+void GenerateJspbFileOrder(const std::vector<const FileDescriptor*>& input,
+ std::vector<const FileDescriptor*>* ordered) {
+ // First generate an ordering of all reachable files (including dependencies)
+ // with depth-first search. This mimics the behavior of --include_imports,
+ // which is what the old codegen used.
+ ordered->clear();
+ std::set<const FileDescriptor*> seen;
+ std::set<const FileDescriptor*> input_set;
+ for (int i = 0; i < input.size(); i++) {
+ DepthFirstSearch(input[i], ordered, &seen);
+ input_set.insert(input[i]);
+ }
+
+ // Now remove the entries that are not actually in our input list.
+ ordered->erase(
+ std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)),
+ ordered->end());
+}
+
+// If we're generating code in file-per-type mode, avoid overwriting files
+// by choosing the last descriptor that writes each filename and permitting
+// only those to generate code.
+
+struct DepsGenerator {
+ std::vector<const Descriptor*> operator()(const Descriptor* desc) const {
+ std::vector<const Descriptor*> deps;
+ auto maybe_add = [&](const Descriptor* d) {
+ if (d) deps.push_back(d);
+ };
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (!IgnoreField(desc->field(i))) {
+ maybe_add(desc->field(i)->message_type());
+ }
+ }
+ for (int i = 0; i < desc->extension_count(); i++) {
+ maybe_add(desc->extension(i)->message_type());
+ maybe_add(desc->extension(i)->containing_type());
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ maybe_add(desc->nested_type(i));
+ }
+ maybe_add(desc->containing_type());
+
+ return deps;
+ }
+};
+
+bool GenerateJspbAllowedMap(const GeneratorOptions& options,
+ const std::vector<const FileDescriptor*>& files,
+ std::map<const void*, std::string>* allowed_set,
+ SCCAnalyzer<DepsGenerator>* analyzer) {
+ std::vector<const FileDescriptor*> files_ordered;
+ GenerateJspbFileOrder(files, &files_ordered);
+
+ // Choose the last descriptor for each filename.
+ FileDeduplicator dedup(options);
+ std::set<const SCC*> added;
+ for (int i = 0; i < files_ordered.size(); i++) {
+ for (int j = 0; j < files_ordered[i]->message_type_count(); j++) {
+ const Descriptor* desc = files_ordered[i]->message_type(j);
+ if (added.insert(analyzer->GetSCC(desc)).second &&
+ !dedup.AddFile(
+ std::make_pair(
+ GetMessagesFileName(options, analyzer->GetSCC(desc), false),
+ GetMessagesFileName(options, analyzer->GetSCC(desc), true)),
+ analyzer->GetSCC(desc))) {
+ return false;
+ }
+ }
+ for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) {
+ const EnumDescriptor* desc = files_ordered[i]->enum_type(j);
+ if (!dedup.AddFile(std::make_pair(GetEnumFileName(options, desc, false),
+ GetEnumFileName(options, desc, true)),
+ desc)) {
+ return false;
+ }
+ }
+
+ // Pull out all free-floating extensions and generate files for those too.
+ bool has_extension = false;
+
+ for (int j = 0; j < files_ordered[i]->extension_count(); j++) {
+ if (ShouldGenerateExtension(files_ordered[i]->extension(j))) {
+ has_extension = true;
+ }
+ }
+
+ if (has_extension) {
+ if (!dedup.AddFile(
+ std::make_pair(
+ GetExtensionFileName(options, files_ordered[i], false),
+ GetExtensionFileName(options, files_ordered[i], true)),
+ files_ordered[i])) {
+ return false;
+ }
+ }
+ }
+
+ dedup.GetAllowedMap(allowed_set);
+
+ return true;
+}
+
+// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of
+// file.
+void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations,
+ io::Printer* printer) {
+ // Serialize annotations proto into base64 string.
+ std::string meta_content;
+ annotations.SerializeToString(&meta_content);
+ std::string meta_64;
+ Base64Escape(meta_content, &meta_64);
+
+ // Print base64 encoded annotations at the end of output file in
+ // a comment.
+ printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto");
+ printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64);
+}
+
+bool IsWellKnownTypeFile(const FileDescriptor* file) {
+ return HasPrefixString(file->name(), "google/protobuf/");
+}
+
+} // anonymous namespace
+
+void Generator::GenerateHeader(const GeneratorOptions& options,
+ const FileDescriptor* file,
+ io::Printer* printer) const {
+ if (file != nullptr) {
+ printer->Print("// source: $filename$\n", "filename", file->name());
+ }
+ printer->Print(
+ "/**\n"
+ " * @fileoverview\n"
+ " * @enhanceable\n"
+ // TODO(b/152440355): requireType/requires diverged from internal version.
+ " * @suppress {missingRequire} reports error on implicit type usages.\n"
+ " * @suppress {messageConventions} JS Compiler reports an "
+ "error if a variable or\n"
+ " * field starts with 'MSG_' and isn't a translatable "
+ "message.\n"
+ " * @public\n"
+ " */\n"
+ "// GENERATED CODE -- DO NOT EDIT!\n"
+ "/* eslint-disable */\n"
+ "// @ts-nocheck\n"
+ "\n");
+}
+
+void Generator::FindProvidesForFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file,
+ std::set<std::string>* provided) const {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ FindProvidesForMessage(options, printer, file->message_type(i), provided);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ FindProvidesForEnum(options, printer, file->enum_type(i), provided);
+ }
+}
+
+void Generator::FindProvides(const GeneratorOptions& options,
+ io::Printer* printer,
+ const std::vector<const FileDescriptor*>& files,
+ std::set<std::string>* provided) const {
+ for (int i = 0; i < files.size(); i++) {
+ FindProvidesForFile(options, printer, files[i], provided);
+ }
+
+ printer->Print("\n");
+}
+
+void FindProvidesForOneOfEnum(const GeneratorOptions& options,
+ const OneofDescriptor* oneof,
+ std::set<std::string>* provided) {
+ std::string name = GetMessagePath(options, oneof->containing_type()) + "." +
+ JSOneofName(oneof) + "Case";
+ provided->insert(name);
+}
+
+void FindProvidesForOneOfEnums(const GeneratorOptions& options,
+ io::Printer* printer, const Descriptor* desc,
+ std::set<std::string>* provided) {
+ if (HasOneofFields(desc)) {
+ for (int i = 0; i < desc->oneof_decl_count(); i++) {
+ if (IgnoreOneof(desc->oneof_decl(i))) {
+ continue;
+ }
+ FindProvidesForOneOfEnum(options, desc->oneof_decl(i), provided);
+ }
+ }
+}
+
+void Generator::FindProvidesForMessage(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc,
+ std::set<std::string>* provided) const {
+ if (IgnoreMessage(desc)) {
+ return;
+ }
+
+ std::string name = GetMessagePath(options, desc);
+ provided->insert(name);
+
+ for (int i = 0; i < desc->enum_type_count(); i++) {
+ FindProvidesForEnum(options, printer, desc->enum_type(i), provided);
+ }
+
+ FindProvidesForOneOfEnums(options, printer, desc, provided);
+
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ FindProvidesForMessage(options, printer, desc->nested_type(i), provided);
+ }
+}
+void Generator::FindProvidesForEnum(const GeneratorOptions& options,
+ io::Printer* printer,
+ const EnumDescriptor* enumdesc,
+ std::set<std::string>* provided) const {
+ std::string name = GetEnumPath(options, enumdesc);
+ provided->insert(name);
+}
+
+void Generator::FindProvidesForFields(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FieldDescriptor*>& fields,
+ std::set<std::string>* provided) const {
+ for (int i = 0; i < fields.size(); i++) {
+ const FieldDescriptor* field = fields[i];
+
+ if (IgnoreField(field)) {
+ continue;
+ }
+
+ std::string name = GetNamespace(options, field->file()) + "." +
+ JSObjectFieldName(options, field);
+ provided->insert(name);
+ }
+}
+
+void Generator::GenerateProvides(const GeneratorOptions& options,
+ io::Printer* printer,
+ std::set<std::string>* provided) const {
+ for (std::set<std::string>::iterator it = provided->begin();
+ it != provided->end(); ++it) {
+ if (options.import_style == GeneratorOptions::kImportClosure) {
+ printer->Print("goog.provide('$name$');\n", "name", *it);
+ } else {
+ // We aren't using Closure's import system, but we use goog.exportSymbol()
+ // to construct the expected tree of objects, eg.
+ //
+ // goog.exportSymbol('foo.bar.Baz', null, this);
+ //
+ // // Later generated code expects foo.bar = {} to exist:
+ // foo.bar.Baz = function() { /* ... */ }
+
+ // Do not use global scope in strict mode
+ if (options.import_style == GeneratorOptions::kImportCommonJsStrict) {
+ std::string namespaceObject = *it;
+ // Remove "proto." from the namespace object
+ GOOGLE_CHECK_EQ(0, namespaceObject.compare(0, 6, "proto."));
+ namespaceObject.erase(0, 6);
+ printer->Print("goog.exportSymbol('$name$', null, proto);\n", "name",
+ namespaceObject);
+ } else {
+ printer->Print("goog.exportSymbol('$name$', null, global);\n", "name",
+ *it);
+ }
+ }
+ }
+}
+
+void Generator::GenerateRequiresForSCC(const GeneratorOptions& options,
+ io::Printer* printer, const SCC* scc,
+ std::set<std::string>* provided) const {
+ std::set<std::string> required;
+ std::set<std::string> forwards;
+ bool have_message = false;
+ bool has_extension = false;
+ bool has_map = false;
+ for (auto desc : scc->descriptors) {
+ if (desc->containing_type() == nullptr) {
+ FindRequiresForMessage(options, desc, &required, &forwards,
+ &have_message);
+ has_extension = (has_extension || HasExtensions(desc));
+ has_map = (has_map || HasMap(options, desc));
+ }
+ }
+
+ GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+ /* require_jspb = */ have_message,
+ /* require_extension = */ has_extension,
+ /* require_map = */ has_map);
+}
+
+void Generator::GenerateRequiresForLibrary(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FileDescriptor*>& files,
+ std::set<std::string>* provided) const {
+ GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure);
+ // For Closure imports we need to import every message type individually.
+ std::set<std::string> required;
+ std::set<std::string> forwards;
+ bool have_extensions = false;
+ bool have_map = false;
+ bool have_message = false;
+
+ for (int i = 0; i < files.size(); i++) {
+ for (int j = 0; j < files[i]->message_type_count(); j++) {
+ const Descriptor* desc = files[i]->message_type(j);
+ if (!IgnoreMessage(desc)) {
+ FindRequiresForMessage(options, desc, &required, &forwards,
+ &have_message);
+ }
+ }
+
+ if (!have_extensions && HasExtensions(files[i])) {
+ have_extensions = true;
+ }
+
+ if (!have_map && FileHasMap(options, files[i])) {
+ have_map = true;
+ }
+
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ const FieldDescriptor* extension = files[i]->extension(j);
+ if (IgnoreField(extension)) {
+ continue;
+ }
+ if (extension->containing_type()->full_name() !=
+ "google.protobuf.bridge.MessageSet") {
+ required.insert(GetMessagePath(options, extension->containing_type()));
+ }
+ FindRequiresForField(options, extension, &required, &forwards);
+ have_extensions = true;
+ }
+ }
+
+ GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+ /* require_jspb = */ have_message,
+ /* require_extension = */ have_extensions,
+ /* require_map = */ have_map);
+}
+
+void Generator::GenerateRequiresForExtensions(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FieldDescriptor*>& fields,
+ std::set<std::string>* provided) const {
+ std::set<std::string> required;
+ std::set<std::string> forwards;
+ for (int i = 0; i < fields.size(); i++) {
+ const FieldDescriptor* field = fields[i];
+ if (IgnoreField(field)) {
+ continue;
+ }
+ FindRequiresForExtension(options, field, &required, &forwards);
+ }
+
+ GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+ /* require_jspb = */ false,
+ /* require_extension = */ fields.size() > 0,
+ /* require_map = */ false);
+}
+
+void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
+ io::Printer* printer,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards,
+ std::set<std::string>* provided,
+ bool require_jspb, bool require_extension,
+ bool require_map) const {
+ if (require_jspb) {
+ required->insert("jspb.Message");
+ required->insert("jspb.BinaryReader");
+ required->insert("jspb.BinaryWriter");
+ }
+ if (require_extension) {
+ required->insert("jspb.ExtensionFieldBinaryInfo");
+ required->insert("jspb.ExtensionFieldInfo");
+ }
+ if (require_map) {
+ required->insert("jspb.Map");
+ }
+
+ std::set<std::string>::iterator it;
+ for (it = required->begin(); it != required->end(); ++it) {
+ if (provided->find(*it) != provided->end()) {
+ continue;
+ }
+ printer->Print("goog.require('$name$');\n", "name", *it);
+ }
+
+ printer->Print("\n");
+
+ for (it = forwards->begin(); it != forwards->end(); ++it) {
+ if (provided->find(*it) != provided->end()) {
+ continue;
+ }
+ printer->Print("goog.forwardDeclare('$name$');\n", "name", *it);
+ }
+}
+
+bool NamespaceOnly(const Descriptor* desc) { return false; }
+
+void Generator::FindRequiresForMessage(const GeneratorOptions& options,
+ const Descriptor* desc,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards,
+ bool* have_message) const {
+ if (!NamespaceOnly(desc)) {
+ *have_message = true;
+ for (int i = 0; i < desc->field_count(); i++) {
+ const FieldDescriptor* field = desc->field(i);
+ if (IgnoreField(field)) {
+ continue;
+ }
+ FindRequiresForField(options, field, required, forwards);
+ }
+ }
+
+ for (int i = 0; i < desc->extension_count(); i++) {
+ const FieldDescriptor* field = desc->extension(i);
+ if (IgnoreField(field)) {
+ continue;
+ }
+ FindRequiresForExtension(options, field, required, forwards);
+ }
+
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ FindRequiresForMessage(options, desc->nested_type(i), required, forwards,
+ have_message);
+ }
+}
+
+void Generator::FindRequiresForField(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards) const {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+ // N.B.: file-level extensions with enum type do *not* create
+ // dependencies, as per original codegen.
+ !(field->is_extension() && field->extension_scope() == nullptr)) {
+ if (options.add_require_for_enums) {
+ required->insert(GetEnumPath(options, field->enum_type()));
+ } else {
+ forwards->insert(GetEnumPath(options, field->enum_type()));
+ }
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (!IgnoreMessage(field->message_type())) {
+ required->insert(GetMessagePath(options, field->message_type()));
+ }
+ }
+}
+
+void Generator::FindRequiresForExtension(
+ const GeneratorOptions& options, const FieldDescriptor* field,
+ std::set<std::string>* required, std::set<std::string>* forwards) const {
+ if (field->containing_type()->full_name() !=
+ "google.protobuf.bridge.MessageSet") {
+ required->insert(GetMessagePath(options, field->containing_type()));
+ }
+ FindRequiresForField(options, field, required, forwards);
+}
+
+void Generator::GenerateTestOnly(const GeneratorOptions& options,
+ io::Printer* printer) const {
+ if (options.testonly) {
+ printer->Print("goog.setTestOnly();\n\n");
+ }
+ printer->Print("\n");
+}
+
+void Generator::GenerateClassesAndEnums(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file) const {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateClassConstructorAndDeclareExtensionFieldInfo(options, printer,
+ file->message_type(i));
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateClass(options, printer, file->message_type(i));
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnum(options, printer, file->enum_type(i));
+ }
+}
+
+void Generator::GenerateClass(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ if (IgnoreMessage(desc)) {
+ return;
+ }
+
+ if (!NamespaceOnly(desc)) {
+ printer->Print("\n");
+ GenerateClassFieldInfo(options, printer, desc);
+
+ GenerateClassToObject(options, printer, desc);
+ // These must come *before* the extension-field info generation in
+ // GenerateClassRegistration so that references to the binary
+ // serialization/deserialization functions may be placed in the extension
+ // objects.
+ GenerateClassDeserializeBinary(options, printer, desc);
+ GenerateClassSerializeBinary(options, printer, desc);
+ }
+
+ // Recurse on nested types. These must come *before* the extension-field
+ // info generation in GenerateClassRegistration so that extensions that
+ // reference nested types proceed the definitions of the nested types.
+ for (int i = 0; i < desc->enum_type_count(); i++) {
+ GenerateEnum(options, printer, desc->enum_type(i));
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ GenerateClass(options, printer, desc->nested_type(i));
+ }
+
+ if (!NamespaceOnly(desc)) {
+ GenerateClassRegistration(options, printer, desc);
+ GenerateClassFields(options, printer, desc);
+
+ if (options.import_style != GeneratorOptions::kImportClosure) {
+ for (int i = 0; i < desc->extension_count(); i++) {
+ GenerateExtension(options, printer, desc->extension(i));
+ }
+ }
+ }
+}
+
+void Generator::GenerateClassConstructor(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ printer->Print(
+ "/**\n"
+ " * Generated by JsPbCodeGenerator.\n"
+ " * @param {Array=} opt_data Optional initial data array, typically "
+ "from a\n"
+ " * server response, or constructed directly in Javascript. The array "
+ "is used\n"
+ " * in place and becomes part of the constructed object. It is not "
+ "cloned.\n"
+ " * If no data is provided, the constructed object will be empty, but "
+ "still\n"
+ " * valid.\n"
+ " * @extends {jspb.Message}\n"
+ " * @constructor\n"
+ " */\n"
+ "$classprefix$$classname$ = function(opt_data) {\n",
+ "classprefix", GetMessagePathPrefix(options, desc), "classname",
+ desc->name());
+ printer->Annotate("classname", desc);
+ std::string message_id = GetMessageId(desc);
+ printer->Print(
+ " jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, "
+ "$rptfields$, $oneoffields$);\n",
+ "messageId",
+ !message_id.empty() ? ("'" + message_id + "'")
+ : (IsResponse(desc) ? "''" : "0"),
+ "pivot", GetPivot(desc), "rptfields",
+ RepeatedFieldsArrayName(options, desc), "oneoffields",
+ OneofFieldsArrayName(options, desc));
+ printer->Print(
+ "};\n"
+ "goog.inherits($classname$, jspb.Message);\n"
+ "if (goog.DEBUG && !COMPILED) {\n"
+ // displayName overrides Function.prototype.displayName
+ // http://google3/javascript/externs/es3.js?l=511
+ " /**\n"
+ " * @public\n"
+ " * @override\n"
+ " */\n"
+ " $classname$.displayName = '$classname$';\n"
+ "}\n",
+ "classname", GetMessagePath(options, desc));
+}
+
+void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo(
+ const GeneratorOptions& options, io::Printer* printer,
+ const Descriptor* desc) const {
+ if (!NamespaceOnly(desc)) {
+ GenerateClassConstructor(options, printer, desc);
+ if (IsExtendable(desc) &&
+ desc->full_name() != "google.protobuf.bridge.MessageSet") {
+ GenerateClassExtensionFieldInfo(options, printer, desc);
+ }
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ if (!IgnoreMessage(desc->nested_type(i))) {
+ GenerateClassConstructorAndDeclareExtensionFieldInfo(
+ options, printer, desc->nested_type(i));
+ }
+ }
+}
+
+void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ if (HasRepeatedFields(options, desc)) {
+ printer->Print(
+ "/**\n"
+ " * List of repeated fields within this message type.\n"
+ " * @private {!Array<number>}\n"
+ " * @const\n"
+ " */\n"
+ "$classname$$rptfieldarray$ = $rptfields$;\n"
+ "\n",
+ "classname", GetMessagePath(options, desc), "rptfieldarray",
+ kRepeatedFieldArrayName, "rptfields",
+ RepeatedFieldNumberList(options, desc));
+ }
+
+ if (HasOneofFields(desc)) {
+ printer->Print(
+ "/**\n"
+ " * Oneof group definitions for this message. Each group defines the "
+ "field\n"
+ " * numbers belonging to that group. When of these fields' value is "
+ "set, all\n"
+ " * other fields in the group are cleared. During deserialization, if "
+ "multiple\n"
+ " * fields are encountered for a group, only the last value seen will "
+ "be kept.\n"
+ " * @private {!Array<!Array<number>>}\n"
+ " * @const\n"
+ " */\n"
+ "$classname$$oneofgrouparray$ = $oneofgroups$;\n"
+ "\n",
+ "classname", GetMessagePath(options, desc), "oneofgrouparray",
+ kOneofGroupArrayName, "oneofgroups", OneofGroupList(desc));
+
+ for (int i = 0; i < desc->oneof_decl_count(); i++) {
+ if (IgnoreOneof(desc->oneof_decl(i))) {
+ continue;
+ }
+ GenerateOneofCaseDefinition(options, printer, desc->oneof_decl(i));
+ }
+ }
+}
+
+void Generator::GenerateClassXid(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ printer->Print(
+ "\n"
+ "\n"
+ "$class$.prototype.messageXid = xid('$class$');\n",
+ "class", GetMessagePath(options, desc));
+}
+
+void Generator::GenerateOneofCaseDefinition(
+ const GeneratorOptions& options, io::Printer* printer,
+ const OneofDescriptor* oneof) const {
+ printer->Print(
+ "/**\n"
+ " * @enum {number}\n"
+ " */\n"
+ "$classname$.$oneof$Case = {\n"
+ " $upcase$_NOT_SET: 0",
+ "classname", GetMessagePath(options, oneof->containing_type()), "oneof",
+ JSOneofName(oneof), "upcase", ToEnumCase(oneof->name()));
+
+ for (int i = 0; i < oneof->field_count(); i++) {
+ if (IgnoreField(oneof->field(i))) {
+ continue;
+ }
+
+ printer->Print(
+ ",\n"
+ " $upcase$: $number$",
+ "upcase", ToEnumCase(oneof->field(i)->name()), "number",
+ JSFieldIndex(oneof->field(i)));
+ printer->Annotate("upcase", oneof->field(i));
+ }
+
+ printer->Print(
+ "\n"
+ "};\n"
+ "\n"
+ "/**\n"
+ " * @return {$class$.$oneof$Case}\n"
+ " */\n"
+ "$class$.prototype.get$oneof$Case = function() {\n"
+ " return /** @type {$class$.$oneof$Case} */(jspb.Message."
+ "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n"
+ "};\n"
+ "\n",
+ "class", GetMessagePath(options, oneof->containing_type()), "oneof",
+ JSOneofName(oneof), "oneofindex", JSOneofIndex(oneof));
+}
+
+void Generator::GenerateClassToObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ printer->Print(
+ "\n"
+ "\n"
+ "if (jspb.Message.GENERATE_TO_OBJECT) {\n"
+ "/**\n"
+ " * Creates an object representation of this proto.\n"
+ " * Field names that are reserved in JavaScript and will be renamed to "
+ "pb_name.\n"
+ " * Optional fields that are not set will be set to undefined.\n"
+ " * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.\n"
+ " * For the list of reserved names please see:\n"
+ " * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n"
+ " * @param {boolean=} opt_includeInstance Deprecated. whether to include "
+ "the\n"
+ " * JSPB instance for transitional soy proto support:\n"
+ " * http://goto/soy-param-migration\n"
+ " * @return {!Object}\n"
+ " */\n"
+ "$classname$.prototype.toObject = function(opt_includeInstance) {\n"
+ " return $classname$.toObject(opt_includeInstance, this);\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Static version of the {@see toObject} method.\n"
+ " * @param {boolean|undefined} includeInstance Deprecated. Whether to "
+ "include\n"
+ " * the JSPB instance for transitional soy proto support:\n"
+ " * http://goto/soy-param-migration\n"
+ " * @param {!$classname$} msg The msg instance to transform.\n"
+ " * @return {!Object}\n"
+ " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
+ " */\n"
+ "$classname$.toObject = function(includeInstance, msg) {\n"
+ " var f, obj = {",
+ "classname", GetMessagePath(options, desc));
+
+ bool first = true;
+ for (int i = 0; i < desc->field_count(); i++) {
+ const FieldDescriptor* field = desc->field(i);
+ if (IgnoreField(field)) {
+ continue;
+ }
+
+ if (!first) {
+ printer->Print(",\n ");
+ } else {
+ printer->Print("\n ");
+ first = false;
+ }
+
+ GenerateClassFieldToObject(options, printer, field);
+ }
+
+ if (!first) {
+ printer->Print("\n };\n\n");
+ } else {
+ printer->Print("\n\n };\n\n");
+ }
+
+ if (IsExtendable(desc)) {
+ printer->Print(
+ " jspb.Message.toObjectExtension(/** @type {!jspb.Message} */ (msg), "
+ "obj,\n"
+ " $extObject$, $class$.prototype.getExtension,\n"
+ " includeInstance);\n",
+ "extObject", JSExtensionsObjectName(options, desc->file(), desc),
+ "class", GetMessagePath(options, desc));
+ }
+
+ printer->Print(
+ " if (includeInstance) {\n"
+ " obj.$$jspbMessageInstance = msg;\n"
+ " }\n"
+ " return obj;\n"
+ "};\n"
+ "}\n"
+ "\n"
+ "\n",
+ "classname", GetMessagePath(options, desc));
+}
+
+void Generator::GenerateFieldValueExpression(io::Printer* printer,
+ const char* obj_reference,
+ const FieldDescriptor* field,
+ bool use_default) const {
+ const bool is_float_or_double =
+ field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE;
+ const bool is_boolean = field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL;
+
+ const std::string with_default = use_default ? "WithDefault" : "";
+ const std::string default_arg =
+ use_default ? StrCat(", ", JSFieldDefault(field)) : "";
+ const std::string cardinality = field->is_repeated() ? "Repeated" : "";
+ std::string type = "";
+ if (is_float_or_double) {
+ type = "FloatingPoint";
+ }
+ if (is_boolean) {
+ type = "Boolean";
+ }
+
+ // Prints the appropriate function, among:
+ // - getField
+ // - getBooleanField
+ // - getFloatingPointField => Replaced by getOptionalFloatingPointField to
+ // preserve backward compatibility.
+ // - getFieldWithDefault
+ // - getBooleanFieldWithDefault
+ // - getFloatingPointFieldWithDefault
+ // - getRepeatedField
+ // - getRepeatedBooleanField
+ // - getRepeatedFloatingPointField
+ if (is_float_or_double && !field->is_repeated() && !use_default) {
+ printer->Print(
+ "jspb.Message.getOptionalFloatingPointField($obj$, "
+ "$index$$default$)",
+ "obj", obj_reference, "index", JSFieldIndex(field), "default",
+ default_arg);
+ } else {
+ printer->Print(
+ "jspb.Message.get$cardinality$$type$Field$with_default$($obj$, "
+ "$index$$default$)",
+ "cardinality", cardinality, "type", type, "with_default", with_default,
+ "obj", obj_reference, "index", JSFieldIndex(field), "default",
+ default_arg);
+ }
+}
+
+void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const {
+ printer->Print("$fieldname$: ", "fieldname",
+ JSObjectFieldName(options, field));
+
+ if (field->is_map()) {
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ // If the map values are of a message type, we must provide their static
+ // toObject() method; otherwise we pass undefined for that argument.
+ std::string value_to_object;
+ if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ value_to_object =
+ GetMessagePath(options, value_field->message_type()) + ".toObject";
+ } else {
+ value_to_object = "undefined";
+ }
+ printer->Print(
+ "(f = msg.get$name$()) ? f.toObject(includeInstance, $valuetoobject$) "
+ ": []",
+ "name", JSGetterName(options, field), "valuetoobject", value_to_object);
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message field.
+ if (field->is_repeated()) {
+ {
+ printer->Print(
+ "jspb.Message.toObjectList(msg.get$getter$(),\n"
+ " $type$.toObject, includeInstance)",
+ "getter", JSGetterName(options, field), "type",
+ SubmessageTypeRef(options, field));
+ }
+ } else {
+ printer->Print(
+ "(f = msg.get$getter$()) && "
+ "$type$.toObject(includeInstance, f)",
+ "getter", JSGetterName(options, field), "type",
+ SubmessageTypeRef(options, field));
+ }
+ } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ // For bytes fields we want to always return the B64 data.
+ printer->Print("msg.get$getter$()", "getter",
+ JSGetterName(options, field, BYTES_B64));
+ } else {
+ bool use_default = field->has_default_value();
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ // Repeated fields get initialized to their default in the constructor
+ // (why?), so we emit a plain getField() call for them.
+ !field->is_repeated()) {
+ // Proto3 puts all defaults (including implicit defaults) in toObject().
+ // But for proto2 we leave the existing semantics unchanged: unset fields
+ // without default are unset.
+ use_default = true;
+ }
+
+ // We don't implement this by calling the accessors, because the semantics
+ // of the accessors are changing independently of the toObject() semantics.
+ // We are migrating the accessors to return defaults instead of null, but
+ // it may take longer to migrate toObject (or we might not want to do it at
+ // all). So we want to generate independent code.
+ // The accessor for unset optional values without default should return
+ // null. Those are converted to undefined in the generated object.
+ if (!use_default) {
+ printer->Print("(f = ");
+ }
+ GenerateFieldValueExpression(printer, "msg", field, use_default);
+ if (!use_default) {
+ printer->Print(") == null ? undefined : f");
+ }
+ }
+}
+
+void Generator::GenerateObjectTypedef(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ // TODO(b/122687752): Consider renaming nested messages called ObjectFormat
+ // to prevent collisions.
+ const std::string type_name = GetMessagePath(options, desc) + ".ObjectFormat";
+
+ printer->Print(
+ "/**\n"
+ " * The raw object form of $messageName$ as accepted by the `fromObject` "
+ "method.\n"
+ " * @record\n"
+ " */\n"
+ "$typeName$ = function() {\n",
+ "messageName", desc->name(), "typeName", type_name);
+
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (i > 0) {
+ printer->Print("\n");
+ }
+ printer->Print(
+ " /** @type {$fieldType$|undefined} */\n"
+ " this.$fieldName$;\n",
+ "fieldName", JSObjectFieldName(options, desc->field(i)),
+ // TODO(b/121097361): Add type checking for field values.
+ "fieldType", "?");
+ }
+
+ printer->Print("};\n\n");
+}
+
+void Generator::GenerateClassFromObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ printer->Print("if (jspb.Message.GENERATE_FROM_OBJECT) {\n\n");
+
+ GenerateObjectTypedef(options, printer, desc);
+
+ printer->Print(
+ "/**\n"
+ " * Loads data from an object into a new instance of this proto.\n"
+ " * @param {!$classname$.ObjectFormat} obj\n"
+ " * The object representation of this proto to load the data from.\n"
+ " * @return {!$classname$}\n"
+ " */\n"
+ "$classname$.fromObject = function(obj) {\n"
+ " var msg = new $classname$();\n",
+ "classname", GetMessagePath(options, desc));
+
+ for (int i = 0; i < desc->field_count(); i++) {
+ const FieldDescriptor* field = desc->field(i);
+ if (!IgnoreField(field)) {
+ GenerateClassFieldFromObject(options, printer, field);
+ }
+ }
+
+ printer->Print(
+ " return msg;\n"
+ "};\n"
+ "}\n\n");
+}
+
+void Generator::GenerateClassFieldFromObject(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const {
+ if (field->is_map()) {
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ // Since the map values are of message type, we have to do some extra work
+ // to recursively call fromObject() on them before setting the map field.
+ printer->Print(
+ " obj.$name$ && jspb.Message.setWrapperField(\n"
+ " msg, $index$, jspb.Map.fromObject(obj.$name$, $fieldclass$, "
+ "$fieldclass$.fromObject));\n",
+ "name", JSObjectFieldName(options, field), "index",
+ JSFieldIndex(field), "fieldclass",
+ GetMessagePath(options, value_field->message_type()));
+ } else {
+ // `msg` is a newly-constructed message object that has not yet built any
+ // map containers wrapping underlying arrays, so we can simply directly
+ // set the array here without fear of a stale wrapper.
+ printer->Print(
+ " obj.$name$ && "
+ "jspb.Message.setField(msg, $index$, obj.$name$);\n",
+ "name", JSObjectFieldName(options, field), "index",
+ JSFieldIndex(field));
+ }
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message field (singular or repeated)
+ if (field->is_repeated()) {
+ {
+ printer->Print(
+ " obj.$name$ && "
+ "jspb.Message.setRepeatedWrapperField(\n"
+ " msg, $index$, obj.$name$.map(\n"
+ " $fieldclass$.fromObject));\n",
+ "name", JSObjectFieldName(options, field), "index",
+ JSFieldIndex(field), "fieldclass",
+ SubmessageTypeRef(options, field));
+ }
+ } else {
+ printer->Print(
+ " obj.$name$ && jspb.Message.setWrapperField(\n"
+ " msg, $index$, $fieldclass$.fromObject(obj.$name$));\n",
+ "name", JSObjectFieldName(options, field), "index",
+ JSFieldIndex(field), "fieldclass", SubmessageTypeRef(options, field));
+ }
+ } else {
+ // Simple (primitive) field.
+ printer->Print(
+ " obj.$name$ != null && jspb.Message.setField(msg, $index$, "
+ "obj.$name$);\n",
+ "name", JSObjectFieldName(options, field), "index",
+ JSFieldIndex(field));
+ }
+}
+
+void Generator::GenerateClassRegistration(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ // Register any extensions defined inside this message type.
+ for (int i = 0; i < desc->extension_count(); i++) {
+ const FieldDescriptor* extension = desc->extension(i);
+ if (ShouldGenerateExtension(extension)) {
+ GenerateExtension(options, printer, extension);
+ }
+ }
+}
+
+void Generator::GenerateClassFields(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (!IgnoreField(desc->field(i))) {
+ GenerateClassField(options, printer, desc->field(i));
+ }
+ }
+}
+
+void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field, BytesMode bytes_mode) {
+ std::string type =
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false, bytes_mode);
+ printer->Print(
+ "/**\n"
+ " * $fielddef$\n"
+ "$comment$"
+ " * This is a type-conversion wrapper around `get$defname$()`\n"
+ " * @return {$type$}\n"
+ " */\n"
+ "$class$.prototype.get$name$ = function() {\n"
+ " return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n"
+ " this.get$defname$()));\n"
+ "};\n"
+ "\n"
+ "\n",
+ "fielddef", FieldDefinition(options, field), "comment",
+ FieldComments(field, bytes_mode), "type", type, "class",
+ GetMessagePath(options, field->containing_type()), "name",
+ JSGetterName(options, field, bytes_mode), "list",
+ field->is_repeated() ? "List" : "", "suffix",
+ JSByteGetterSuffix(bytes_mode), "defname",
+ JSGetterName(options, field, BYTES_DEFAULT));
+}
+
+void Generator::GenerateClassField(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const {
+ if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ // Map field: special handling to instantiate the map object on demand.
+ std::string key_type =
+ JSFieldTypeAnnotation(options, key_field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ true,
+ /* singular_if_not_packed = */ false);
+ std::string value_type =
+ JSFieldTypeAnnotation(options, value_field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ true,
+ /* singular_if_not_packed = */ false);
+
+ printer->Print(
+ "/**\n"
+ " * $fielddef$\n"
+ " * @param {boolean=} opt_noLazyCreate Do not create the map if\n"
+ " * empty, instead returning `undefined`\n"
+ " * @return {!jspb.Map<$keytype$,$valuetype$>}\n"
+ " */\n",
+ "fielddef", FieldDefinition(options, field), "keytype", key_type,
+ "valuetype", value_type);
+ printer->Print(
+ "$class$.prototype.$gettername$ = function(opt_noLazyCreate) {\n"
+ " return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field), "keytype", key_type,
+ "valuetype", value_type);
+ printer->Annotate("gettername", field);
+ printer->Print(
+ " jspb.Message.getMapField(this, $index$, opt_noLazyCreate",
+ "index", JSFieldIndex(field));
+
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(
+ ",\n"
+ " $messageType$",
+ "messageType", GetMessagePath(options, value_field->message_type()));
+ } else {
+ printer->Print(
+ ",\n"
+ " null");
+ }
+
+ printer->Print("));\n");
+
+ printer->Print(
+ "};\n"
+ "\n"
+ "\n");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message field: special handling in order to wrap the underlying data
+ // array with a message object.
+
+ printer->Print(
+ "/**\n"
+ " * $fielddef$\n"
+ "$comment$"
+ " * @return {$type$}\n"
+ " */\n",
+ "fielddef", FieldDefinition(options, field), "comment",
+ FieldComments(field, BYTES_DEFAULT), "type",
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false));
+ printer->Print(
+ "$class$.prototype.$gettername$ = function() {\n"
+ " return /** @type{$type$} */ (\n"
+ " jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, "
+ "$index$$required$));\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field), "type",
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false),
+ "rpt", (field->is_repeated() ? "Repeated" : ""), "index",
+ JSFieldIndex(field), "wrapperclass", SubmessageTypeRef(options, field),
+ "required",
+ (field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : ""));
+ printer->Annotate("gettername", field);
+ printer->Print(
+ "/**\n"
+ " * @param {$optionaltype$} value\n"
+ " * @return {!$class$} returns this\n"
+ "*/\n"
+ "$class$.prototype.$settername$ = function(value) {\n"
+ " return jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
+ "optionaltype",
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ true,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false),
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field), "oneoftag",
+ (InRealOneof(field) ? "Oneof" : ""), "repeatedtag",
+ (field->is_repeated() ? "Repeated" : ""));
+ printer->Annotate("settername", field);
+
+ printer->Print(
+ "this, $index$$oneofgroup$, value);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "index", JSFieldIndex(field), "oneofgroup",
+ (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""));
+
+ if (field->is_repeated()) {
+ GenerateRepeatedMessageHelperMethods(options, printer, field);
+ }
+
+ } else {
+ bool untyped = false;
+
+ // Simple (primitive) field, either singular or repeated.
+
+ // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
+ // at this point we "lie" to non-binary users and tell the return
+ // type is always base64 string, pending a LSC to migrate to typed getters.
+ BytesMode bytes_mode =
+ field->type() == FieldDescriptor::TYPE_BYTES && !options.binary
+ ? BYTES_B64
+ : BYTES_DEFAULT;
+ std::string typed_annotation =
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false,
+ /* bytes_mode = */ bytes_mode);
+ if (untyped) {
+ printer->Print(
+ "/**\n"
+ " * @return {?} Raw field, untyped.\n"
+ " */\n");
+ } else {
+ printer->Print(
+ "/**\n"
+ " * $fielddef$\n"
+ "$comment$"
+ " * @return {$type$}\n"
+ " */\n",
+ "fielddef", FieldDefinition(options, field), "comment",
+ FieldComments(field, bytes_mode), "type", typed_annotation);
+ }
+
+ printer->Print("$class$.prototype.$gettername$ = function() {\n", "class",
+ GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field));
+ printer->Annotate("gettername", field);
+
+ if (untyped) {
+ printer->Print(" return ");
+ } else {
+ printer->Print(" return /** @type {$type$} */ (", "type",
+ typed_annotation);
+ }
+
+ bool use_default = !ReturnsNullWhenUnset(options, field);
+
+ // Raw fields with no default set should just return undefined.
+ if (untyped && !field->has_default_value()) {
+ use_default = false;
+ }
+
+ // Repeated fields get initialized to their default in the constructor
+ // (why?), so we emit a plain getField() call for them.
+ if (field->is_repeated()) {
+ use_default = false;
+ }
+
+ GenerateFieldValueExpression(printer, "this", field, use_default);
+
+ if (untyped) {
+ printer->Print(
+ ";\n"
+ "};\n"
+ "\n"
+ "\n");
+ } else {
+ printer->Print(
+ ");\n"
+ "};\n"
+ "\n"
+ "\n");
+ }
+
+ if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
+ GenerateBytesWrapper(options, printer, field, BYTES_B64);
+ GenerateBytesWrapper(options, printer, field, BYTES_U8);
+ }
+
+ printer->Print(
+ "/**\n"
+ " * @param {$optionaltype$} value\n"
+ " * @return {!$class$} returns this\n"
+ " */\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "optionaltype",
+ untyped ? "*"
+ : JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ true,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false));
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ !field->is_repeated() && !field->is_map() &&
+ !HasFieldPresence(options, field)) {
+ // Proto3 non-repeated and non-map fields without presence use the
+ // setProto3*Field function.
+ printer->Print(
+ "$class$.prototype.$settername$ = function(value) {\n"
+ " return jspb.Message.setProto3$typetag$Field(this, $index$, "
+ "value);"
+ "\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field), "typetag",
+ JSTypeTag(field), "index", JSFieldIndex(field));
+ printer->Annotate("settername", field);
+ } else {
+ // Otherwise, use the regular setField function.
+ printer->Print(
+ "$class$.prototype.$settername$ = function(value) {\n"
+ " return jspb.Message.set$oneoftag$Field(this, $index$",
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field), "oneoftag",
+ (InRealOneof(field) ? "Oneof" : ""), "index", JSFieldIndex(field));
+ printer->Annotate("settername", field);
+ printer->Print(
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "type",
+ untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+ "typeclose", untyped ? ")" : "", "oneofgroup",
+ (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""),
+ "rptvalueinit", (field->is_repeated() ? " || []" : ""));
+ }
+
+ if (untyped) {
+ printer->Print(
+ "/**\n"
+ " * Clears the value.\n"
+ " * @return {!$class$} returns this\n"
+ " */\n",
+ "class", GetMessagePath(options, field->containing_type()));
+ }
+
+ if (field->is_repeated()) {
+ GenerateRepeatedPrimitiveHelperMethods(options, printer, field, untyped);
+ }
+ }
+
+ // Generate clearFoo() method for map fields, repeated fields, and other
+ // fields with presence.
+ if (field->is_map()) {
+ // clang-format off
+ printer->Print(
+ "/**\n"
+ " * Clears values from the map. The map will be non-null.\n"
+ " * @return {!$class$} returns this\n"
+ " */\n"
+ "$class$.prototype.$clearername$ = function() {\n"
+ " this.$gettername$().clear();\n"
+ " return this;"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
+ "gettername", "get" + JSGetterName(options, field));
+ // clang-format on
+ printer->Annotate("clearername", field);
+ } else if (field->is_repeated() ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !field->is_required())) {
+ // Fields where we can delegate to the regular setter.
+ // clang-format off
+ printer->Print(
+ "/**\n"
+ " * $jsdoc$\n"
+ " * @return {!$class$} returns this\n"
+ " */\n"
+ "$class$.prototype.$clearername$ = function() {\n"
+ " return this.$settername$($clearedvalue$);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "jsdoc", field->is_repeated()
+ ? "Clears the list making it empty but non-null."
+ : "Clears the message field making it undefined.",
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
+ "settername", "set" + JSGetterName(options, field),
+ "clearedvalue", (field->is_repeated() ? "[]" : "undefined"));
+ // clang-format on
+ printer->Annotate("clearername", field);
+ } else if (HasFieldPresence(options, field)) {
+ // Fields where we can't delegate to the regular setter because it doesn't
+ // accept "undefined" as an argument.
+ // clang-format off
+ printer->Print(
+ "/**\n"
+ " * Clears the field making it undefined.\n"
+ " * @return {!$class$} returns this\n"
+ " */\n"
+ "$class$.prototype.$clearername$ = function() {\n"
+ " return jspb.Message.set$maybeoneof$Field(this, "
+ "$index$$maybeoneofgroup$, ",
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
+ "maybeoneof", (InRealOneof(field) ? "Oneof" : ""),
+ "maybeoneofgroup", (InRealOneof(field)
+ ? (", " + JSOneofArray(options, field))
+ : ""),
+ "index", JSFieldIndex(field));
+ // clang-format on
+ printer->Annotate("clearername", field);
+ printer->Print(
+ "$clearedvalue$);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "clearedvalue", (field->is_repeated() ? "[]" : "undefined"));
+ }
+
+ if (HasFieldPresence(options, field)) {
+ printer->Print(
+ "/**\n"
+ " * Returns whether this field is set.\n"
+ " * @return {boolean}\n"
+ " */\n"
+ "$class$.prototype.$hasername$ = function() {\n"
+ " return jspb.Message.getField(this, $index$) != null;\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()), "hasername",
+ "has" + JSGetterName(options, field), "index", JSFieldIndex(field));
+ printer->Annotate("hasername", field);
+ }
+}
+
+void Generator::GenerateRepeatedPrimitiveHelperMethods(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field, bool untyped) const {
+ // clang-format off
+ printer->Print(
+ "/**\n"
+ " * @param {$optionaltype$} value\n"
+ " * @param {number=} opt_index\n"
+ " * @return {!$class$} returns this\n"
+ " */\n"
+ "$class$.prototype.$addername$ = function(value, opt_index) {\n"
+ " return jspb.Message.addToRepeatedField(this, "
+ "$index$",
+ "class", GetMessagePath(options, field->containing_type()), "addername",
+ "add" + JSGetterName(options, field, BYTES_DEFAULT,
+ /* drop_list = */ true),
+ "optionaltype",
+ JSFieldTypeAnnotation(
+ options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ true,
+ /* singular_if_not_packed = */ false,
+ BYTES_DEFAULT,
+ /* force_singular = */ true),
+ "index", JSFieldIndex(field));
+ printer->Annotate("addername", field);
+ printer->Print(
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, "
+ "opt_index);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "",
+ "typeclose", untyped ? ")" : "", "oneofgroup",
+ (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""),
+ "rptvalueinit", "");
+ // clang-format on
+}
+
+void Generator::GenerateRepeatedMessageHelperMethods(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const {
+ printer->Print(
+ "/**\n"
+ " * @param {!$optionaltype$=} opt_value\n"
+ " * @param {number=} opt_index\n"
+ " * @return {!$optionaltype$}\n"
+ " */\n"
+ "$class$.prototype.$addername$ = function(opt_value, opt_index) {\n"
+ " return jspb.Message.addTo$repeatedtag$WrapperField(",
+ "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class",
+ GetMessagePath(options, field->containing_type()), "addername",
+ "add" + JSGetterName(options, field, BYTES_DEFAULT,
+ /* drop_list = */ true),
+ "repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+
+ printer->Annotate("addername", field);
+ printer->Print(
+ "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "index", JSFieldIndex(field), "oneofgroup",
+ (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "ctor",
+ GetMessagePath(options, field->message_type()));
+}
+
+void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ if (IsExtendable(desc)) {
+ printer->Print(
+ "\n"
+ "/**\n"
+ " * The extensions registered with this message class. This is a "
+ "map of\n"
+ " * extension field number to fieldInfo object.\n"
+ " *\n"
+ " * For example:\n"
+ " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, "
+ "ctor: proto.example.MyMessage} }\n"
+ " *\n"
+ " * fieldName contains the JsCompiler renamed field name property "
+ "so that it\n"
+ " * works in OPTIMIZED mode.\n"
+ " *\n"
+ " * @type {!Object<number, jspb.ExtensionFieldInfo>}\n"
+ " */\n"
+ "$class$.extensions = {};\n"
+ "\n",
+ "class", GetMessagePath(options, desc));
+
+ printer->Print(
+ "\n"
+ "/**\n"
+ " * The extensions registered with this message class. This is a "
+ "map of\n"
+ " * extension field number to fieldInfo object.\n"
+ " *\n"
+ " * For example:\n"
+ " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, "
+ "ctor: proto.example.MyMessage} }\n"
+ " *\n"
+ " * fieldName contains the JsCompiler renamed field name property "
+ "so that it\n"
+ " * works in OPTIMIZED mode.\n"
+ " *\n"
+ " * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}\n"
+ " */\n"
+ "$class$.extensionsBinary = {};\n"
+ "\n",
+ "class", GetMessagePath(options, desc));
+ }
+}
+
+void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ // TODO(cfallin): Handle lazy decoding when requested by field option and/or
+ // by default for 'bytes' fields and packed repeated fields.
+
+ printer->Print(
+ "/**\n"
+ " * Deserializes binary data (in protobuf wire format).\n"
+ " * @param {jspb.ByteSource} bytes The bytes to deserialize.\n"
+ " * @return {!$class$}\n"
+ " */\n"
+ "$class$.deserializeBinary = function(bytes) {\n"
+ " var reader = new jspb.BinaryReader(bytes);\n"
+ " var msg = new $class$;\n"
+ " return $class$.deserializeBinaryFromReader(msg, reader);\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Deserializes binary data (in protobuf wire format) from the\n"
+ " * given reader into the given message object.\n"
+ " * @param {!$class$} msg The message object to deserialize into.\n"
+ " * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n"
+ " * @return {!$class$}\n"
+ " */\n"
+ "$class$.deserializeBinaryFromReader = function(msg, reader) {\n"
+ " while (reader.nextField()) {\n",
+ "class", GetMessagePath(options, desc));
+ printer->Print(
+ " if (reader.isEndGroup()) {\n"
+ " break;\n"
+ " }\n"
+ " var field = reader.getFieldNumber();\n"
+ " switch (field) {\n");
+
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (!IgnoreField(desc->field(i))) {
+ GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
+ }
+ }
+
+ printer->Print(" default:\n");
+ if (IsExtendable(desc)) {
+ printer->Print(
+ " jspb.Message.readBinaryExtension(msg, reader,\n"
+ " $extobj$Binary,\n"
+ " $class$.prototype.getExtension,\n"
+ " $class$.prototype.setExtension);\n"
+ " break;\n"
+ " }\n",
+ "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class",
+ GetMessagePath(options, desc));
+ } else {
+ printer->Print(
+ " reader.skipField();\n"
+ " break;\n"
+ " }\n");
+ }
+
+ printer->Print(
+ " }\n"
+ " return msg;\n"
+ "};\n"
+ "\n"
+ "\n");
+}
+
+void Generator::GenerateClassDeserializeBinaryField(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const {
+ printer->Print(" case $num$:\n", "num", StrCat(field->number()));
+
+ if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ printer->Print(
+ " var value = msg.get$name$();\n"
+ " reader.readMessage(value, function(message, reader) {\n",
+ "name", JSGetterName(options, field));
+
+ printer->Print(
+ " jspb.Map.deserializeBinary(message, reader, "
+ "$keyReaderFn$, $valueReaderFn$",
+ "keyReaderFn", JSBinaryReaderMethodName(options, key_field),
+ "valueReaderFn", JSBinaryReaderMethodName(options, value_field));
+
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(", $messageType$.deserializeBinaryFromReader",
+ "messageType",
+ GetMessagePath(options, value_field->message_type()));
+ } else {
+ printer->Print(", null");
+ }
+ printer->Print(", $defaultKey$", "defaultKey", JSFieldDefault(key_field));
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(", new $messageType$()", "messageType",
+ GetMessagePath(options, value_field->message_type()));
+ } else {
+ printer->Print(", $defaultValue$", "defaultValue",
+ JSFieldDefault(value_field));
+ }
+ printer->Print(");\n");
+ printer->Print(" });\n");
+ } else {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ " var value = new $fieldclass$;\n"
+ " reader.read$msgOrGroup$($grpfield$value,"
+ "$fieldclass$.deserializeBinaryFromReader);\n",
+ "fieldclass", SubmessageTypeRef(options, field), "msgOrGroup",
+ (field->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message",
+ "grpfield",
+ (field->type() == FieldDescriptor::TYPE_GROUP)
+ ? (StrCat(field->number()) + ", ")
+ : "");
+ } else if (field->is_packable()) {
+ printer->Print(
+ " var values = /** @type {$fieldtype$} */ "
+ "(reader.isDelimited() "
+ "? reader.readPacked$reader$() : [reader.read$reader$()]);\n",
+ "fieldtype",
+ JSFieldTypeAnnotation(options, field, false, true,
+ /* singular_if_not_packed */ false, BYTES_U8),
+ "reader", JSBinaryReaderMethodType(field));
+ } else {
+ printer->Print(
+ " var value = /** @type {$fieldtype$} */ "
+ "(reader.read$reader$());\n",
+ "fieldtype",
+ JSFieldTypeAnnotation(options, field, false, true,
+ /* singular_if_not_packed */ true, BYTES_U8),
+ "reader",
+ JSBinaryReadWriteMethodName(field, /* is_writer = */ false));
+ }
+
+ if (field->is_packable()) {
+ printer->Print(
+ " for (var i = 0; i < values.length; i++) {\n"
+ " msg.add$name$(values[i]);\n"
+ " }\n",
+ "name",
+ JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true));
+ } else if (field->is_repeated()) {
+ printer->Print(
+ " msg.add$name$(value);\n", "name",
+ JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true));
+ } else {
+ // Singular fields, and packed repeated fields, receive a |value| either
+ // as the field's value or as the array of all the field's values; set
+ // this as the field's value directly.
+ printer->Print(" msg.set$name$(value);\n", "name",
+ JSGetterName(options, field));
+ }
+ }
+
+ printer->Print(" break;\n");
+}
+
+void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const {
+ printer->Print(
+ "/**\n"
+ " * Serializes the message to binary data (in protobuf wire format).\n"
+ " * @return {!Uint8Array}\n"
+ " */\n"
+ "$class$.prototype.serializeBinary = function() {\n"
+ " var writer = new jspb.BinaryWriter();\n"
+ " $class$.serializeBinaryToWriter(this, writer);\n"
+ " return writer.getResultBuffer();\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Serializes the given message to binary data (in protobuf wire\n"
+ " * format), writing to the given BinaryWriter.\n"
+ " * @param {!$class$} message\n"
+ " * @param {!jspb.BinaryWriter} writer\n"
+ " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
+ " */\n"
+ "$class$.serializeBinaryToWriter = function(message, "
+ "writer) {\n"
+ " var f = undefined;\n",
+ "class", GetMessagePath(options, desc));
+
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (!IgnoreField(desc->field(i))) {
+ GenerateClassSerializeBinaryField(options, printer, desc->field(i));
+ }
+ }
+
+ if (IsExtendable(desc)) {
+ printer->Print(
+ " jspb.Message.serializeBinaryExtensions(message, writer,\n"
+ " $extobj$Binary, $class$.prototype.getExtension);\n",
+ "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class",
+ GetMessagePath(options, desc));
+ }
+
+ printer->Print(
+ "};\n"
+ "\n"
+ "\n");
+}
+
+void Generator::GenerateClassSerializeBinaryField(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const {
+ if (HasFieldPresence(options, field) &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ std::string typed_annotation =
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false,
+ /* bytes_mode = */ BYTES_DEFAULT);
+ printer->Print(
+ " f = /** @type {$type$} */ "
+ "(jspb.Message.getField(message, $index$));\n",
+ "index", JSFieldIndex(field), "type", typed_annotation);
+ } else {
+ printer->Print(
+ " f = message.get$name$($nolazy$);\n", "name",
+ JSGetterName(options, field, BYTES_U8),
+ // No lazy creation for maps containers -- fastpath the empty case.
+ "nolazy", field->is_map() ? "true" : "");
+ }
+
+ // Print an `if (condition)` statement that evaluates to true if the field
+ // goes on the wire.
+ if (field->is_map()) {
+ printer->Print(" if (f && f.getLength() > 0) {\n");
+ } else if (field->is_repeated()) {
+ printer->Print(" if (f.length > 0) {\n");
+ } else {
+ if (HasFieldPresence(options, field)) {
+ printer->Print(" if (f != null) {\n");
+ } else {
+ // No field presence: serialize onto the wire only if value is
+ // non-default. Defaults are documented here:
+ // https://goto.google.com/lhdfm
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT32:
+ case FieldDescriptor::CPPTYPE_UINT64: {
+ if (IsIntegralFieldWithStringJSType(field)) {
+ // We can use `parseInt` here even though it will not be precise for
+ // 64-bit quantities because we are only testing for zero/nonzero,
+ // and JS numbers (64-bit floating point values, i.e., doubles) are
+ // integer-precise in the range that includes zero.
+ printer->Print(" if (parseInt(f, 10) !== 0) {\n");
+ } else {
+ printer->Print(" if (f !== 0) {\n");
+ }
+ break;
+ }
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ printer->Print(" if (f !== 0.0) {\n");
+ break;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ printer->Print(" if (f) {\n");
+ break;
+ case FieldDescriptor::CPPTYPE_STRING:
+ printer->Print(" if (f.length > 0) {\n");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+ }
+
+ // Write the field on the wire.
+ if (field->is_map()) {
+ const FieldDescriptor* key_field = MapFieldKey(field);
+ const FieldDescriptor* value_field = MapFieldValue(field);
+ printer->Print(
+ " f.serializeBinary($index$, writer, "
+ "$keyWriterFn$, $valueWriterFn$",
+ "index", StrCat(field->number()), "keyWriterFn",
+ JSBinaryWriterMethodName(options, key_field), "valueWriterFn",
+ JSBinaryWriterMethodName(options, value_field));
+
+ if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ printer->Print(", $messageType$.serializeBinaryToWriter", "messageType",
+ GetMessagePath(options, value_field->message_type()));
+ }
+
+ printer->Print(");\n");
+ } else {
+ printer->Print(
+ " writer.write$method$(\n"
+ " $index$,\n"
+ " f",
+ "method", JSBinaryReadWriteMethodName(field, /* is_writer = */ true),
+ "index", StrCat(field->number()));
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !field->is_map()) {
+ printer->Print(
+ ",\n"
+ " $submsg$.serializeBinaryToWriter\n",
+ "submsg", SubmessageTypeRef(options, field));
+ } else {
+ printer->Print("\n");
+ }
+
+ printer->Print(" );\n");
+ }
+
+ // Close the `if`.
+ printer->Print(" }\n");
+}
+
+void Generator::GenerateEnum(const GeneratorOptions& options,
+ io::Printer* printer,
+ const EnumDescriptor* enumdesc) const {
+ printer->Print(
+ "/**\n"
+ " * @enum {number}\n"
+ " */\n"
+ "$enumprefix$$name$ = {\n",
+ "enumprefix", GetEnumPathPrefix(options, enumdesc), "name",
+ enumdesc->name());
+ printer->Annotate("name", enumdesc);
+
+ std::set<std::string> used_name;
+ std::vector<int> valid_index;
+ for (int i = 0; i < enumdesc->value_count(); i++) {
+ if (enumdesc->options().allow_alias() &&
+ !used_name.insert(ToEnumCase(enumdesc->value(i)->name())).second) {
+ continue;
+ }
+ valid_index.push_back(i);
+ }
+ for (auto i : valid_index) {
+ const EnumValueDescriptor* value = enumdesc->value(i);
+ printer->Print(" $name$: $value$$comma$\n", "name",
+ ToEnumCase(value->name()), "value", StrCat(value->number()),
+ "comma", (i == valid_index.back()) ? "" : ",");
+ printer->Annotate("name", value);
+ }
+
+ printer->Print(
+ "};\n"
+ "\n");
+}
+
+void Generator::GenerateExtension(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const {
+ std::string extension_scope =
+ (field->extension_scope()
+ ? GetMessagePath(options, field->extension_scope())
+ : GetNamespace(options, field->file()));
+
+ const std::string extension_object_name = JSObjectFieldName(options, field);
+ printer->Print(
+ "\n"
+ "/**\n"
+ " * A tuple of {field number, class constructor} for the extension\n"
+ " * field named `$nameInComment$`.\n"
+ " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n"
+ " */\n"
+ "$class$.$name$ = new jspb.ExtensionFieldInfo(\n",
+ "nameInComment", extension_object_name, "name", extension_object_name,
+ "class", extension_scope, "extensionType",
+ JSFieldTypeAnnotation(options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ true,
+ /* singular_if_not_packed = */ false));
+ printer->Annotate("name", field);
+ printer->Print(
+ " $index$,\n"
+ " {$name$: 0},\n"
+ " $ctor$,\n"
+ " /** @type {?function((boolean|undefined),!jspb.Message=): "
+ "!Object} */ (\n"
+ " $toObject$),\n"
+ " $repeated$);\n",
+ "index", StrCat(field->number()), "name", extension_object_name, "ctor",
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+ ? SubmessageTypeRef(options, field)
+ : std::string("null")),
+ "toObject",
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+ ? (SubmessageTypeRef(options, field) + ".toObject")
+ : std::string("null")),
+ "repeated", (field->is_repeated() ? "1" : "0"));
+
+ printer->Print(
+ "\n"
+ "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n"
+ " $class$.$name$,\n"
+ " $binaryReaderFn$,\n"
+ " $binaryWriterFn$,\n"
+ " $binaryMessageSerializeFn$,\n"
+ " $binaryMessageDeserializeFn$,\n",
+ "extendName",
+ JSExtensionsObjectName(options, field->file(), field->containing_type()),
+ "index", StrCat(field->number()), "class", extension_scope, "name",
+ extension_object_name, "binaryReaderFn",
+ JSBinaryReaderMethodName(options, field), "binaryWriterFn",
+ JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn",
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
+ ? (SubmessageTypeRef(options, field) + ".serializeBinaryToWriter")
+ : "undefined",
+ "binaryMessageDeserializeFn",
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
+ ? (SubmessageTypeRef(options, field) + ".deserializeBinaryFromReader")
+ : "undefined");
+
+ printer->Print(" $isPacked$);\n", "isPacked",
+ (field->is_packed() ? "true" : "false"));
+
+ printer->Print(
+ "// This registers the extension field with the extended class, so that\n"
+ "// toObject() will function correctly.\n"
+ "$extendName$[$index$] = $class$.$name$;\n"
+ "\n",
+ "extendName",
+ JSExtensionsObjectName(options, field->file(), field->containing_type()),
+ "index", StrCat(field->number()), "class", extension_scope, "name",
+ extension_object_name);
+}
+
+bool GeneratorOptions::ParseFromOptions(
+ const std::vector<std::pair<std::string, std::string> >& options,
+ std::string* error) {
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "add_require_for_enums") {
+ if (options[i].second != "") {
+ *error = "Unexpected option value for add_require_for_enums";
+ return false;
+ }
+ add_require_for_enums = true;
+ } else if (options[i].first == "binary") {
+ if (options[i].second != "") {
+ *error = "Unexpected option value for binary";
+ return false;
+ }
+ binary = true;
+ } else if (options[i].first == "testonly") {
+ if (options[i].second != "") {
+ *error = "Unexpected option value for testonly";
+ return false;
+ }
+ testonly = true;
+
+ } else if (options[i].first == "error_on_name_conflict") {
+ GOOGLE_LOG(WARNING) << "Ignoring error_on_name_conflict option, this "
+ "will be removed in a future release";
+ } else if (options[i].first == "output_dir") {
+ output_dir = options[i].second;
+ } else if (options[i].first == "namespace_prefix") {
+ namespace_prefix = options[i].second;
+ } else if (options[i].first == "library") {
+ library = options[i].second;
+ } else if (options[i].first == "import_style") {
+ if (options[i].second == "closure") {
+ import_style = kImportClosure;
+ } else if (options[i].second == "commonjs") {
+ import_style = kImportCommonJs;
+ } else if (options[i].second == "commonjs_strict") {
+ import_style = kImportCommonJsStrict;
+ } else if (options[i].second == "browser") {
+ import_style = kImportBrowser;
+ } else if (options[i].second == "es6") {
+ import_style = kImportEs6;
+ } else {
+ *error = "Unknown import style " + options[i].second + ", expected " +
+ "one of: closure, commonjs, browser, es6.";
+ }
+ } else if (options[i].first == "extension") {
+ extension = options[i].second;
+ } else if (options[i].first == "one_output_file_per_input_file") {
+ if (!options[i].second.empty()) {
+ *error = "Unexpected option value for one_output_file_per_input_file";
+ return false;
+ }
+ one_output_file_per_input_file = true;
+ } else if (options[i].first == "annotate_code") {
+ if (!options[i].second.empty()) {
+ *error = "Unexpected option value for annotate_code";
+ return false;
+ }
+ annotate_code = true;
+ } else {
+ // Assume any other option is an output directory, as long as it is a bare
+ // `key` rather than a `key=value` option.
+ if (options[i].second != "") {
+ *error = "Unknown option: " + options[i].first;
+ return false;
+ }
+ output_dir = options[i].first;
+ }
+ }
+
+ if (import_style != kImportClosure &&
+ (add_require_for_enums || testonly || !library.empty() ||
+ extension != ".js" || one_output_file_per_input_file)) {
+ *error =
+ "The add_require_for_enums, testonly, library, extension, and "
+ "one_output_file_per_input_file options should only be "
+ "used for import_style=closure";
+ return false;
+ }
+
+ return true;
+}
+
+GeneratorOptions::OutputMode GeneratorOptions::output_mode() const {
+ // We use one output file per input file if we are not using Closure or if
+ // this is explicitly requested.
+ if (import_style != kImportClosure || one_output_file_per_input_file) {
+ return kOneOutputFilePerInputFile;
+ }
+
+ // If a library name is provided, we put everything in that one file.
+ if (!library.empty()) {
+ return kEverythingInOneFile;
+ }
+
+ // Otherwise, we create one output file per SCC.
+ return kOneOutputFilePerSCC;
+}
+
+void Generator::GenerateFilesInDepOrder(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FileDescriptor*>& files) const {
+ // Build a std::set over all files so that the DFS can detect when it recurses
+ // into a dep not specified in the user's command line.
+ std::set<const FileDescriptor*> all_files(files.begin(), files.end());
+ // Track the in-progress set of files that have been generated already.
+ std::set<const FileDescriptor*> generated;
+ for (int i = 0; i < files.size(); i++) {
+ GenerateFileAndDeps(options, printer, files[i], &all_files, &generated);
+ }
+}
+
+void Generator::GenerateFileAndDeps(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FileDescriptor* root, std::set<const FileDescriptor*>* all_files,
+ std::set<const FileDescriptor*>* generated) const {
+ // Skip if already generated.
+ if (generated->find(root) != generated->end()) {
+ return;
+ }
+ generated->insert(root);
+
+ // Generate all dependencies before this file's content.
+ for (int i = 0; i < root->dependency_count(); i++) {
+ const FileDescriptor* dep = root->dependency(i);
+ GenerateFileAndDeps(options, printer, dep, all_files, generated);
+ }
+
+ // Generate this file's content. Only generate if the file is part of the
+ // original set requested to be generated; i.e., don't take all transitive
+ // deps down to the roots.
+ if (all_files->find(root) != all_files->end()) {
+ GenerateClassesAndEnums(options, printer, root);
+ }
+}
+
+bool Generator::GenerateFile(const FileDescriptor* file,
+ const GeneratorOptions& options,
+ GeneratorContext* context,
+ bool use_short_name) const {
+ std::string filename =
+ options.output_dir + "/" +
+ GetJSFilename(options, use_short_name
+ ? file->name().substr(file->name().rfind('/'))
+ : file->name());
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ GOOGLE_CHECK(output);
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(output.get(), '$',
+ options.annotate_code ? &annotation_collector : nullptr);
+
+ GenerateFile(options, &printer, file);
+
+ if (printer.failed()) {
+ return false;
+ }
+
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
+
+ return true;
+}
+
+void Generator::GenerateFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file) const {
+ GenerateHeader(options, file, printer);
+
+ // Generate "require" statements.
+ if ((options.import_style == GeneratorOptions::kImportCommonJs ||
+ options.import_style == GeneratorOptions::kImportCommonJsStrict)) {
+ printer->Print("var jspb = require('google-protobuf');\n");
+ printer->Print("var goog = jspb;\n");
+
+ // Do not use global scope in strict mode
+ if (options.import_style == GeneratorOptions::kImportCommonJsStrict) {
+ printer->Print("var proto = {};\n\n");
+ } else {
+ // To get the global object we call a function with .call(null), this will set "this" inside the
+ // function to the global object.
+ // This does not work if we are running in strict mode ("use strict"),
+ // so we fallback to the following things (in order from first to last):
+ // - window: defined in browsers
+ // - global: defined in most server side environments like NodeJS
+ // - self: defined inside Web Workers (WorkerGlobalScope)
+ // - Function('return this')(): this will work on most platforms, but it may be blocked by things like CSP.
+ // Function('') is almost the same as eval('')
+ printer->Print(
+ "var global = (function() {\n"
+ " if (this) { return this; }\n"
+ " if (typeof window !== 'undefined') { return window; }\n"
+ " if (typeof global !== 'undefined') { return global; }\n"
+ " if (typeof self !== 'undefined') { return self; }\n"
+ " return Function('return this')();\n"
+ "}.call(null));\n\n");
+ }
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const std::string& name = file->dependency(i)->name();
+ printer->Print(
+ "var $alias$ = require('$file$');\n"
+ "goog.object.extend(proto, $alias$);\n",
+ "alias", ModuleAlias(name), "file",
+ GetRootPath(file->name(), name) + GetJSFilename(options, name));
+ }
+ }
+
+ std::set<std::string> provided;
+ std::set<const FieldDescriptor*> extensions;
+ for (int i = 0; i < file->extension_count(); i++) {
+ // We honor the jspb::ignore option here only when working with
+ // Closure-style imports. Use of this option is discouraged and so we want
+ // to avoid adding new support for it.
+ if (options.import_style == GeneratorOptions::kImportClosure &&
+ IgnoreField(file->extension(i))) {
+ continue;
+ }
+ provided.insert(GetNamespace(options, file) + "." +
+ JSObjectFieldName(options, file->extension(i)));
+ extensions.insert(file->extension(i));
+ }
+
+ FindProvidesForFile(options, printer, file, &provided);
+ GenerateProvides(options, printer, &provided);
+ std::vector<const FileDescriptor*> files;
+ files.push_back(file);
+ if (options.import_style == GeneratorOptions::kImportClosure) {
+ GenerateRequiresForLibrary(options, printer, files, &provided);
+ }
+
+ GenerateClassesAndEnums(options, printer, file);
+
+ // Generate code for top-level extensions. Extensions nested inside messages
+ // are emitted inside GenerateClassesAndEnums().
+ for (std::set<const FieldDescriptor*>::const_iterator it = extensions.begin();
+ it != extensions.end(); ++it) {
+ GenerateExtension(options, printer, *it);
+ }
+
+ // if provided is empty, do not export anything
+ if (options.import_style == GeneratorOptions::kImportCommonJs &&
+ !provided.empty()) {
+ printer->Print("goog.object.extend(exports, $package$);\n", "package",
+ GetNamespace(options, file));
+ } else if (options.import_style == GeneratorOptions::kImportCommonJsStrict) {
+ printer->Print("goog.object.extend(exports, proto);\n", "package",
+ GetNamespace(options, file));
+ }
+
+ // Emit well-known type methods.
+ for (FileToc* toc = well_known_types_js; toc->name != NULL; toc++) {
+ std::string name = std::string("google/protobuf/") + toc->name;
+ if (name == StripProto(file->name()) + ".js") {
+ printer->Print(toc->data);
+ }
+ }
+}
+
+bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter,
+ GeneratorContext* context,
+ std::string* error) const {
+ std::vector<std::pair<std::string, std::string> > option_pairs;
+ ParseGeneratorParameter(parameter, &option_pairs);
+ GeneratorOptions options;
+ if (!options.ParseFromOptions(option_pairs, error)) {
+ return false;
+ }
+
+ if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
+ // All output should go in a single file.
+ std::string filename = options.output_dir + "/" + options.library +
+ options.GetFileNameExtension();
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ options.annotate_code ? &annotation_collector : nullptr);
+
+ // Pull out all extensions -- we need these to generate all
+ // provides/requires.
+ std::vector<const FieldDescriptor*> extensions;
+ for (int i = 0; i < files.size(); i++) {
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ const FieldDescriptor* extension = files[i]->extension(j);
+ extensions.push_back(extension);
+ }
+ }
+
+ if (files.size() == 1) {
+ GenerateHeader(options, files[0], &printer);
+ } else {
+ GenerateHeader(options, nullptr, &printer);
+ }
+
+ std::set<std::string> provided;
+ FindProvides(options, &printer, files, &provided);
+ FindProvidesForFields(options, &printer, extensions, &provided);
+ GenerateProvides(options, &printer, &provided);
+ GenerateTestOnly(options, &printer);
+ GenerateRequiresForLibrary(options, &printer, files, &provided);
+
+ GenerateFilesInDepOrder(options, &printer, files);
+
+ for (int i = 0; i < extensions.size(); i++) {
+ if (ShouldGenerateExtension(extensions[i])) {
+ GenerateExtension(options, &printer, extensions[i]);
+ }
+ }
+
+ if (printer.failed()) {
+ return false;
+ }
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
+ } else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerSCC) {
+ std::set<const Descriptor*> have_printed;
+ SCCAnalyzer<DepsGenerator> analyzer;
+ std::map<const void*, std::string> allowed_map;
+ if (!GenerateJspbAllowedMap(options, files, &allowed_map, &analyzer)) {
+ return false;
+ }
+
+ bool generated = false;
+ for (int i = 0; i < files.size(); i++) {
+ const FileDescriptor* file = files[i];
+ // Force well known type to generate in a whole file.
+ if (IsWellKnownTypeFile(file)) {
+ if (!GenerateFile(file, options, context, true)) {
+ return false;
+ }
+ generated = true;
+ continue;
+ }
+ for (int j = 0; j < file->message_type_count(); j++) {
+ const Descriptor* desc = file->message_type(j);
+ if (have_printed.count(desc) ||
+ allowed_map.count(analyzer.GetSCC(desc)) == 0) {
+ continue;
+ }
+
+ generated = true;
+ const SCC* scc = analyzer.GetSCC(desc);
+ const std::string& filename = allowed_map[scc];
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ options.annotate_code ? &annotation_collector : nullptr);
+
+ GenerateHeader(options, file, &printer);
+
+ std::set<std::string> provided;
+ for (auto one_desc : scc->descriptors) {
+ if (one_desc->containing_type() == nullptr) {
+ FindProvidesForMessage(options, &printer, one_desc, &provided);
+ }
+ }
+ GenerateProvides(options, &printer, &provided);
+ GenerateTestOnly(options, &printer);
+ GenerateRequiresForSCC(options, &printer, scc, &provided);
+
+ for (auto one_desc : scc->descriptors) {
+ if (one_desc->containing_type() == nullptr) {
+ GenerateClassConstructorAndDeclareExtensionFieldInfo(
+ options, &printer, one_desc);
+ }
+ }
+ for (auto one_desc : scc->descriptors) {
+ if (one_desc->containing_type() == nullptr) {
+ GenerateClass(options, &printer, one_desc);
+ }
+ }
+
+ for (auto one_desc : scc->descriptors) {
+ have_printed.insert(one_desc);
+ }
+
+ if (printer.failed()) {
+ return false;
+ }
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
+ }
+ for (int j = 0; j < file->enum_type_count(); j++) {
+ const EnumDescriptor* enumdesc = file->enum_type(j);
+ if (allowed_map.count(enumdesc) == 0) {
+ continue;
+ }
+
+ generated = true;
+ const std::string& filename = allowed_map[enumdesc];
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ options.annotate_code ? &annotation_collector : nullptr);
+
+ GenerateHeader(options, file, &printer);
+
+ std::set<std::string> provided;
+ FindProvidesForEnum(options, &printer, enumdesc, &provided);
+ GenerateProvides(options, &printer, &provided);
+ GenerateTestOnly(options, &printer);
+
+ GenerateEnum(options, &printer, enumdesc);
+
+ if (printer.failed()) {
+ return false;
+ }
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
+ }
+ // File-level extensions (message-level extensions are generated under
+ // the enclosing message).
+ if (allowed_map.count(file) == 1) {
+ generated = true;
+ const std::string& filename = allowed_map[file];
+
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(
+ output.get(), '$',
+ options.annotate_code ? &annotation_collector : nullptr);
+
+ GenerateHeader(options, file, &printer);
+
+ std::set<std::string> provided;
+ std::vector<const FieldDescriptor*> fields;
+
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ if (ShouldGenerateExtension(files[i]->extension(j))) {
+ fields.push_back(files[i]->extension(j));
+ }
+ }
+
+ FindProvidesForFields(options, &printer, fields, &provided);
+ GenerateProvides(options, &printer, &provided);
+ GenerateTestOnly(options, &printer);
+ GenerateRequiresForExtensions(options, &printer, fields, &provided);
+
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ if (ShouldGenerateExtension(files[i]->extension(j))) {
+ GenerateExtension(options, &printer, files[i]->extension(j));
+ }
+ }
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
+ }
+ }
+ if (!generated) {
+ std::string filename = options.output_dir + "/" +
+ "empty_no_content_void_file" +
+ options.GetFileNameExtension();
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ }
+ } else /* options.output_mode() == kOneOutputFilePerInputFile */ {
+ // Generate one output file per input (.proto) file.
+
+ for (int i = 0; i < files.size(); i++) {
+ const FileDescriptor* file = files[i];
+ if (!GenerateFile(file, options, context, false)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace js
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.h
new file mode 100644
index 00000000..b01b15e8
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/js/js_generator.h
@@ -0,0 +1,336 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates JavaScript code for a given .proto file.
+//
+#ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
+
+#include <set>
+#include <string>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/scc.h>
+#include <compiler/code_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class OneofDescriptor;
+class FileDescriptor;
+
+namespace io {
+class Printer;
+}
+
+namespace compiler {
+namespace js {
+
+struct GeneratorOptions {
+ // Output path.
+ std::string output_dir;
+ // Namespace prefix.
+ std::string namespace_prefix;
+ // Enable binary-format support?
+ bool binary;
+ // What style of imports should be used.
+ enum ImportStyle {
+ kImportClosure, // goog.require()
+ kImportCommonJs, // require()
+ kImportCommonJsStrict, // require() with no global export
+ kImportBrowser, // no import statements
+ kImportEs6, // import { member } from ''
+ } import_style;
+
+ GeneratorOptions()
+ : output_dir("."),
+ namespace_prefix(""),
+ binary(false),
+ import_style(kImportClosure),
+ add_require_for_enums(false),
+ testonly(false),
+ library(""),
+ extension(".js"),
+ one_output_file_per_input_file(false),
+ annotate_code(false) {}
+
+ bool ParseFromOptions(
+ const std::vector<std::pair<std::string, std::string> >& options,
+ std::string* error);
+
+ // Returns the file name extension to use for generated code.
+ std::string GetFileNameExtension() const {
+ return import_style == kImportClosure ? extension : "_pb.js";
+ }
+
+ enum OutputMode {
+ // Create an output file for each input .proto file.
+ kOneOutputFilePerInputFile,
+ // Create an output file for each type.
+ kOneOutputFilePerSCC,
+ // Put everything in a single file named by the library option.
+ kEverythingInOneFile,
+ };
+
+ // Indicates how to output the generated code based on the provided options.
+ OutputMode output_mode() const;
+
+ // The remaining options are only relevant when we are using kImportClosure.
+
+ // Add a `goog.requires()` call for each enum type used. If not set, a
+ // forward declaration with `goog.forwardDeclare` is produced instead.
+ bool add_require_for_enums;
+ // Set this as a test-only module via `goog.setTestOnly();`.
+ bool testonly;
+ // Create a library with name <name>_lib.js rather than a separate .js file
+ // per type?
+ std::string library;
+ // The extension to use for output file names.
+ std::string extension;
+ // Create a separate output file for each input file?
+ bool one_output_file_per_input_file;
+ // If true, we should append annotations as comments on the last line for
+ // generated .js file. Annotations used by tools like https://kythe.io
+ // to provide cross-references between .js and .proto files. Annotations
+ // are encoded as base64 proto of GeneratedCodeInfo message (see
+ // descriptor.proto).
+ bool annotate_code;
+};
+
+// CodeGenerator implementation which generates a JavaScript source file and
+// header. If you create your own protocol compiler binary and you want it to
+// support JavaScript output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+ Generator() {}
+ virtual ~Generator() {}
+
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const override {
+ *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+ return false;
+ }
+
+ bool HasGenerateAll() const override { return true; }
+
+ bool GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter, GeneratorContext* context,
+ std::string* error) const override;
+
+ uint64 GetSupportedFeatures() const override {
+ return FEATURE_PROTO3_OPTIONAL;
+ }
+
+ private:
+ void GenerateHeader(const GeneratorOptions& options,
+ const FileDescriptor* file, io::Printer* printer) const;
+
+ // Generate goog.provides() calls.
+ void FindProvides(const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FileDescriptor*>& file,
+ std::set<std::string>* provided) const;
+ void FindProvidesForFile(const GeneratorOptions& options,
+ io::Printer* printer, const FileDescriptor* file,
+ std::set<std::string>* provided) const;
+ void FindProvidesForMessage(const GeneratorOptions& options,
+ io::Printer* printer, const Descriptor* desc,
+ std::set<std::string>* provided) const;
+ void FindProvidesForEnum(const GeneratorOptions& options,
+ io::Printer* printer, const EnumDescriptor* enumdesc,
+ std::set<std::string>* provided) const;
+ // For extension fields at file scope.
+ void FindProvidesForFields(const GeneratorOptions& options,
+ io::Printer* printer,
+ const std::vector<const FieldDescriptor*>& fields,
+ std::set<std::string>* provided) const;
+ // Print the goog.provides() found by the methods above.
+ void GenerateProvides(const GeneratorOptions& options, io::Printer* printer,
+ std::set<std::string>* provided) const;
+
+ // Generate goog.setTestOnly() if indicated.
+ void GenerateTestOnly(const GeneratorOptions& options,
+ io::Printer* printer) const;
+
+ // Generate goog.requires() calls.
+ void GenerateRequiresForLibrary(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FileDescriptor*>& files,
+ std::set<std::string>* provided) const;
+ void GenerateRequiresForSCC(const GeneratorOptions& options,
+ io::Printer* printer, const SCC* scc,
+ std::set<std::string>* provided) const;
+ // For extension fields at file scope.
+ void GenerateRequiresForExtensions(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FieldDescriptor*>& fields,
+ std::set<std::string>* provided) const;
+ void GenerateRequiresImpl(const GeneratorOptions& options,
+ io::Printer* printer,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards,
+ std::set<std::string>* provided, bool require_jspb,
+ bool require_extension, bool require_map) const;
+ void FindRequiresForMessage(const GeneratorOptions& options,
+ const Descriptor* desc,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards,
+ bool* have_message) const;
+ void FindRequiresForField(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards) const;
+ void FindRequiresForExtension(const GeneratorOptions& options,
+ const FieldDescriptor* field,
+ std::set<std::string>* required,
+ std::set<std::string>* forwards) const;
+ // Generate all things in a proto file into one file.
+ // If use_short_name is true, the generated file's name will only be short
+ // name that without directory, otherwise filename equals file->name()
+ bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options,
+ GeneratorContext* context, bool use_short_name) const;
+ void GenerateFile(const GeneratorOptions& options, io::Printer* printer,
+ const FileDescriptor* file) const;
+
+ // Generate definitions for all message classes and enums in all files,
+ // processing the files in dependence order.
+ void GenerateFilesInDepOrder(
+ const GeneratorOptions& options, io::Printer* printer,
+ const std::vector<const FileDescriptor*>& file) const;
+ // Helper for above.
+ void GenerateFileAndDeps(const GeneratorOptions& options,
+ io::Printer* printer, const FileDescriptor* root,
+ std::set<const FileDescriptor*>* all_files,
+ std::set<const FileDescriptor*>* generated) const;
+
+ // Generate definitions for all message classes and enums.
+ void GenerateClassesAndEnums(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file) const;
+
+ void GenerateFieldValueExpression(io::Printer* printer,
+ const char* obj_reference,
+ const FieldDescriptor* field,
+ bool use_default) const;
+
+ // Generate definition for one class.
+ void GenerateClass(const GeneratorOptions& options, io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassConstructor(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassFieldInfo(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassConstructorAndDeclareExtensionFieldInfo(
+ const GeneratorOptions& options, io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateOneofCaseDefinition(const GeneratorOptions& options,
+ io::Printer* printer,
+ const OneofDescriptor* oneof) const;
+ void GenerateObjectTypedef(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassToObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassFieldToObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+ void GenerateClassFromObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassFieldFromObject(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+ void GenerateClassRegistration(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassFields(const GeneratorOptions& options,
+ io::Printer* printer, const Descriptor* desc) const;
+ void GenerateClassField(const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* desc) const;
+ void GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassDeserialize(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassDeserializeBinary(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassDeserializeBinaryField(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+ void GenerateClassSerializeBinary(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc) const;
+ void GenerateClassSerializeBinaryField(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+
+ // Generate definition for one enum.
+ void GenerateEnum(const GeneratorOptions& options, io::Printer* printer,
+ const EnumDescriptor* enumdesc) const;
+
+ // Generate an extension definition.
+ void GenerateExtension(const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const;
+
+ // Generate addFoo() method for repeated primitive fields.
+ void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field,
+ bool untyped) const;
+
+ // Generate addFoo() method for repeated message fields.
+ void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
+};
+
+} // namespace js
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.cc b/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.cc
new file mode 100644
index 00000000..eaccdcf5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.cc
@@ -0,0 +1,270 @@
+// 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 <compiler/js/well_known_types_embed.h>
+
+struct FileToc well_known_types_js[] = {
+ {"any.js",
+ "/* This code will be inserted into generated code for\n"
+ " * google/protobuf/any.proto. */\n"
+ "\n"
+ "/**\n"
+ " * Returns the type name contained in this instance, if any.\n"
+ " * @return {string|undefined}\n"
+ " */\n"
+ "proto.google.protobuf.Any.prototype.getTypeName = function() {\n"
+ " return this.getTypeUrl().split('/').pop();\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Packs the given message instance into this Any.\n"
+ " * For binary format usage only.\n"
+ " * @param {!Uint8Array} serialized The serialized data to pack.\n"
+ " * @param {string} name The type name of this message object.\n"
+ " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n"
+ " */\n"
+ "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n"
+ " opt_typeUrlPrefix) "
+ "{\n"
+ " if (!opt_typeUrlPrefix) {\n"
+ " opt_typeUrlPrefix = 'type.googleapis.com/';\n"
+ " }\n"
+ "\n"
+ " if (opt_typeUrlPrefix.substr(-1) != '/') {\n"
+ " this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n"
+ " } else {\n"
+ " this.setTypeUrl(opt_typeUrlPrefix + name);\n"
+ " }\n"
+ "\n"
+ " this.setValue(serialized);\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * @template T\n"
+ " * Unpacks this Any into the given message object.\n"
+ " * @param {function(Uint8Array):T} deserialize Function that will "
+ "deserialize\n"
+ " * the binary data properly.\n"
+ " * @param {string} name The expected type name of this message object.\n"
+ " * @return {?T} If the name matched the expected name, returns the "
+ "deserialized\n"
+ " * object, otherwise returns null.\n"
+ " */\n"
+ "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) "
+ "{\n"
+ " if (this.getTypeName() == name) {\n"
+ " return deserialize(this.getValue_asU8());\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
+ "};\n"
+ },
+ {"timestamp.js",
+ "/* This code will be inserted into generated code for\n"
+ " * google/protobuf/timestamp.proto. */\n"
+ "\n"
+ "/**\n"
+ " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n"
+ " * @return {!Date}\n"
+ " */\n"
+ "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n"
+ " var seconds = this.getSeconds();\n"
+ " var nanos = this.getNanos();\n"
+ "\n"
+ " return new Date((seconds * 1000) + (nanos / 1000000));\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Sets the value of this Timestamp object to be the given Date.\n"
+ " * @param {!Date} value The value to set.\n"
+ " */\n"
+ "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n"
+ " this.setSeconds(Math.floor(value.getTime() / 1000));\n"
+ " this.setNanos(value.getMilliseconds() * 1000000);\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Factory method that returns a Timestamp object with value equal to\n"
+ " * the given Date.\n"
+ " * @param {!Date} value The value to set.\n"
+ " * @return {!proto.google.protobuf.Timestamp}\n"
+ " */\n"
+ "proto.google.protobuf.Timestamp.fromDate = function(value) {\n"
+ " var timestamp = new proto.google.protobuf.Timestamp();\n"
+ " timestamp.fromDate(value);\n"
+ " return timestamp;\n"
+ "};\n"},
+ {"struct.js",
+ "/* This code will be inserted into generated code for\n"
+ " * google/protobuf/struct.proto. */\n"
+ "\n"
+ "/**\n"
+ " * Typedef representing plain JavaScript values that can go into a\n"
+ " * Struct.\n"
+ " * @typedef {null|number|string|boolean|Array|Object}\n"
+ " */\n"
+ "proto.google.protobuf.JavaScriptValue;\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Converts this Value object to a plain JavaScript value.\n"
+ " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n"
+ " * value representing this Struct.\n"
+ " */\n"
+ "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n"
+ " var kindCase = proto.google.protobuf.Value.KindCase;\n"
+ " switch (this.getKindCase()) {\n"
+ " case kindCase.NULL_VALUE:\n"
+ " return null;\n"
+ " case kindCase.NUMBER_VALUE:\n"
+ " return this.getNumberValue();\n"
+ " case kindCase.STRING_VALUE:\n"
+ " return this.getStringValue();\n"
+ " case kindCase.BOOL_VALUE:\n"
+ " return this.getBoolValue();\n"
+ " case kindCase.STRUCT_VALUE:\n"
+ " return this.getStructValue().toJavaScript();\n"
+ " case kindCase.LIST_VALUE:\n"
+ " return this.getListValue().toJavaScript();\n"
+ " default:\n"
+ " throw new Error('Unexpected struct type');\n"
+ " }\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Converts this JavaScript value to a new Value proto.\n"
+ " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n"
+ " * convert.\n"
+ " * @return {!proto.google.protobuf.Value} The newly constructed value.\n"
+ " */\n"
+ "proto.google.protobuf.Value.fromJavaScript = function(value) {\n"
+ " var ret = new proto.google.protobuf.Value();\n"
+ " switch (goog.typeOf(value)) {\n"
+ " case 'string':\n"
+ " ret.setStringValue(/** @type {string} */ (value));\n"
+ " break;\n"
+ " case 'number':\n"
+ " ret.setNumberValue(/** @type {number} */ (value));\n"
+ " break;\n"
+ " case 'boolean':\n"
+ " ret.setBoolValue(/** @type {boolean} */ (value));\n"
+ " break;\n"
+ " case 'null':\n"
+ " ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n"
+ " break;\n"
+ " case 'array':\n"
+ " ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n"
+ " /** @type{!Array} */ (value)));\n"
+ " break;\n"
+ " case 'object':\n"
+ " ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n"
+ " /** @type{!Object} */ (value)));\n"
+ " break;\n"
+ " default:\n"
+ " throw new Error('Unexpected struct type.');\n"
+ " }\n"
+ "\n"
+ " return ret;\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Converts this ListValue object to a plain JavaScript array.\n"
+ " * @return {!Array} a plain JavaScript array representing this List.\n"
+ " */\n"
+ "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n"
+ " var ret = [];\n"
+ " var values = this.getValuesList();\n"
+ "\n"
+ " for (var i = 0; i < values.length; i++) {\n"
+ " ret[i] = values[i].toJavaScript();\n"
+ " }\n"
+ "\n"
+ " return ret;\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Constructs a ListValue protobuf from this plain JavaScript array.\n"
+ " * @param {!Array} array a plain JavaScript array\n"
+ " * @return {proto.google.protobuf.ListValue} a new ListValue object\n"
+ " */\n"
+ "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n"
+ " var ret = new proto.google.protobuf.ListValue();\n"
+ "\n"
+ " for (var i = 0; i < array.length; i++) {\n"
+ " "
+ "ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n"
+ " }\n"
+ "\n"
+ " return ret;\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Converts this Struct object to a plain JavaScript object.\n"
+ " * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a "
+ "plain\n"
+ " * JavaScript object representing this Struct.\n"
+ " */\n"
+ "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n"
+ " var ret = {};\n"
+ "\n"
+ " this.getFieldsMap().forEach(function(value, key) {\n"
+ " ret[key] = value.toJavaScript();\n"
+ " });\n"
+ "\n"
+ " return ret;\n"
+ "};\n"
+ "\n"
+ "\n"
+ "/**\n"
+ " * Constructs a Struct protobuf from this plain JavaScript object.\n"
+ " * @param {!Object} obj a plain JavaScript object\n"
+ " * @return {proto.google.protobuf.Struct} a new Struct object\n"
+ " */\n"
+ "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n"
+ " var ret = new proto.google.protobuf.Struct();\n"
+ " var map = ret.getFieldsMap();\n"
+ "\n"
+ " for (var property in obj) {\n"
+ " var val = obj[property];\n"
+ " map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n"
+ " }\n"
+ "\n"
+ " return ret;\n"
+ "};\n"},
+ {NULL, NULL} // Terminate the list.
+};
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.h b/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.h
new file mode 100644
index 00000000..174c665e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/js/well_known_types_embed.h
@@ -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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
+#define GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
+
+#include <stddef.h>
+
+struct FileToc {
+ const char* name;
+ const char* data;
+};
+
+extern struct FileToc well_known_types_js[];
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/main.cc b/NorthstarDedicatedTest/include/protobuf/compiler/main.cc
new file mode 100644
index 00000000..2a5a2267
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/main.cc
@@ -0,0 +1,113 @@
+// 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 <compiler/cpp/cpp_generator.h>
+#include <compiler/java/java_generator.h>
+#include <compiler/java/java_kotlin_generator.h>
+#include <compiler/js/js_generator.h>
+#include <compiler/command_line_interface.h>
+#include <compiler/python/python_generator.h>
+#include <compiler/csharp/csharp_generator.h>
+#include <compiler/objectivec/objectivec_generator.h>
+#include <compiler/php/php_generator.h>
+#include <compiler/ruby/ruby_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+int ProtobufMain(int argc, char* argv[]) {
+
+ CommandLineInterface cli;
+ cli.AllowPlugins("protoc-");
+
+ // Proto2 C++
+ cpp::CppGenerator cpp_generator;
+ cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
+ "Generate C++ header and source.");
+
+#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
+ cpp_generator.set_opensource_runtime(true);
+ cpp_generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
+#endif
+
+ // Proto2 Java
+ java::JavaGenerator java_generator;
+ cli.RegisterGenerator("--java_out", "--java_opt", &java_generator,
+ "Generate Java source file.");
+
+ // Proto2 Kotlin
+ java::KotlinGenerator kt_generator;
+ cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator,
+ "Generate Kotlin file.");
+
+
+ // Proto2 Python
+ python::Generator py_generator;
+ cli.RegisterGenerator("--python_out", "--python_opt", &py_generator,
+ "Generate Python source file.");
+
+ // PHP
+ php::Generator php_generator;
+ cli.RegisterGenerator("--php_out", "--php_opt", &php_generator,
+ "Generate PHP source file.");
+
+ // Ruby
+ ruby::Generator rb_generator;
+ cli.RegisterGenerator("--ruby_out", "--ruby_opt", &rb_generator,
+ "Generate Ruby source file.");
+
+ // CSharp
+ csharp::Generator csharp_generator;
+ cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator,
+ "Generate C# source file.");
+
+ // Objective-C
+ objectivec::ObjectiveCGenerator objc_generator;
+ cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
+ "Generate Objective-C header and source.");
+
+ // JavaScript
+ js::Generator js_generator;
+ cli.RegisterGenerator("--js_out", "--js_opt", &js_generator,
+ "Generate JavaScript source.");
+
+ return cli.Run(argc, argv);
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+int main(int argc, char* argv[]) {
+ return PROTOBUF_NAMESPACE_ID::compiler::ProtobufMain(argc, argv);
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.cc
new file mode 100644
index 00000000..9de6b5b0
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.cc
@@ -0,0 +1,384 @@
+// 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)
+
+#include <compiler/mock_code_generator.h>
+
+#include <stdlib.h>
+
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include <stubs/strutil.h>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/plugin.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <descriptor.pb.h>
+#include <descriptor.h>
+#include <text_format.h>
+#include <gtest/gtest.h>
+#include <stubs/substitute.h>
+
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Returns the list of the names of files in all_files in the form of a
+// comma-separated string.
+std::string CommaSeparatedList(
+ const std::vector<const FileDescriptor*>& all_files) {
+ std::vector<std::string> names;
+ for (size_t i = 0; i < all_files.size(); i++) {
+ names.push_back(all_files[i]->name());
+ }
+ return Join(names, ",");
+}
+
+static const char* kFirstInsertionPointName = "first_mock_insertion_point";
+static const char* kSecondInsertionPointName = "second_mock_insertion_point";
+static const char* kFirstInsertionPoint =
+ "# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
+static const char* kSecondInsertionPoint =
+ " # @@protoc_insertion_point(second_mock_insertion_point) is here\n";
+
+MockCodeGenerator::MockCodeGenerator(const std::string& name) : name_(name) {}
+
+MockCodeGenerator::~MockCodeGenerator() {}
+
+uint64_t MockCodeGenerator::GetSupportedFeatures() const {
+ uint64_t all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL;
+ return all_features & ~suppressed_features_;
+}
+
+void MockCodeGenerator::SuppressFeatures(uint64_t features) {
+ suppressed_features_ = features;
+}
+
+void MockCodeGenerator::ExpectGenerated(
+ const std::string& name, const std::string& parameter,
+ const std::string& insertions, const std::string& file,
+ const std::string& first_message_name,
+ const std::string& first_parsed_file_name,
+ const std::string& output_directory) {
+ std::string content;
+ GOOGLE_CHECK_OK(
+ File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
+ &content, true));
+
+ std::vector<std::string> lines =
+ Split(content, "\n", true);
+
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ for (size_t i = 0; i < lines.size(); i++) {
+ lines[i] += "\n";
+ }
+
+ std::vector<std::string> insertion_list;
+ if (!insertions.empty()) {
+ insertion_list = Split(insertions, ",", true);
+ }
+
+ EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
+ EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_parsed_file_name,
+ first_message_name),
+ lines[0]);
+
+ EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
+ EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
+
+ for (size_t i = 0; i < insertion_list.size(); i++) {
+ EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", file,
+ file, first_message_name),
+ lines[1 + i]);
+ // Second insertion point is indented, so the inserted text should
+ // automatically be indented too.
+ EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
+ file, file, first_message_name),
+ lines[2 + insertion_list.size() + i]);
+ }
+}
+
+namespace {
+void CheckSingleAnnotation(const std::string& expected_file,
+ const std::string& expected_text,
+ const std::string& file_content,
+ const GeneratedCodeInfo::Annotation& annotation) {
+ EXPECT_EQ(expected_file, annotation.source_file());
+ ASSERT_GE(file_content.size(), annotation.begin());
+ ASSERT_GE(file_content.size(), annotation.end());
+ ASSERT_LE(annotation.begin(), annotation.end());
+ EXPECT_EQ(expected_text.size(), annotation.end() - annotation.begin());
+ EXPECT_EQ(expected_text,
+ file_content.substr(annotation.begin(), expected_text.size()));
+}
+} // anonymous namespace
+
+void MockCodeGenerator::CheckGeneratedAnnotations(
+ const std::string& name, const std::string& file,
+ const std::string& output_directory) {
+ std::string file_content;
+ GOOGLE_CHECK_OK(
+ File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
+ &file_content, true));
+ std::string meta_content;
+ GOOGLE_CHECK_OK(File::GetContents(
+ output_directory + "/" + GetOutputFileName(name, file) + ".pb.meta",
+ &meta_content, true));
+ GeneratedCodeInfo annotations;
+ GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations));
+ ASSERT_EQ(7, annotations.annotation_size());
+
+ CheckSingleAnnotation("first_annotation", "first", file_content,
+ annotations.annotation(0));
+ CheckSingleAnnotation("first_path",
+ "test_generator: first_insert,\n foo.proto,\n "
+ "MockCodeGenerator_Annotate,\n foo.proto\n",
+ file_content, annotations.annotation(1));
+ CheckSingleAnnotation("first_path",
+ "test_plugin: first_insert,\n foo.proto,\n "
+ "MockCodeGenerator_Annotate,\n foo.proto\n",
+ file_content, annotations.annotation(2));
+ CheckSingleAnnotation("second_annotation", "second", file_content,
+ annotations.annotation(3));
+ // This annotated text has changed because it was inserted at an indented
+ // insertion point.
+ CheckSingleAnnotation("second_path",
+ "test_generator: second_insert,\n foo.proto,\n "
+ "MockCodeGenerator_Annotate,\n foo.proto\n",
+ file_content, annotations.annotation(4));
+ CheckSingleAnnotation("second_path",
+ "test_plugin: second_insert,\n foo.proto,\n "
+ "MockCodeGenerator_Annotate,\n foo.proto\n",
+ file_content, annotations.annotation(5));
+ CheckSingleAnnotation("third_annotation", "third", file_content,
+ annotations.annotation(6));
+}
+
+bool MockCodeGenerator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* context,
+ std::string* error) const {
+ bool annotate = false;
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
+ std::string command = StripPrefixString(
+ file->message_type(i)->name(), "MockCodeGenerator_");
+ if (command == "Error") {
+ *error = "Saw message type MockCodeGenerator_Error.";
+ return false;
+ } else if (command == "Exit") {
+ std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
+ exit(123);
+ } else if (command == "Abort") {
+ std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
+ abort();
+ } else if (command == "HasSourceCodeInfo") {
+ FileDescriptorProto file_descriptor_proto;
+ file->CopySourceCodeInfoTo(&file_descriptor_proto);
+ bool has_source_code_info =
+ file_descriptor_proto.has_source_code_info() &&
+ file_descriptor_proto.source_code_info().location_size() > 0;
+ std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+ << has_source_code_info << "." << std::endl;
+ abort();
+ } else if (command == "HasJsonName") {
+ FieldDescriptorProto field_descriptor_proto;
+ file->message_type(i)->field(0)->CopyTo(&field_descriptor_proto);
+ std::cerr << "Saw json_name: " << field_descriptor_proto.has_json_name()
+ << std::endl;
+ abort();
+ } else if (command == "Annotate") {
+ annotate = true;
+ } else if (command == "ShowVersionNumber") {
+ Version compiler_version;
+ context->GetCompilerVersion(&compiler_version);
+ std::cerr << "Saw compiler_version: "
+ << compiler_version.major() * 1000000 +
+ compiler_version.minor() * 1000 +
+ compiler_version.patch()
+ << " " << compiler_version.suffix() << std::endl;
+ abort();
+ } else {
+ GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
+ }
+ }
+ }
+
+ bool insert_endlines = HasPrefixString(parameter, "insert_endlines=");
+ if (insert_endlines || HasPrefixString(parameter, "insert=")) {
+ std::vector<std::string> insert_into = Split(
+ StripPrefixString(
+ parameter, insert_endlines ? "insert_endlines=" : "insert="),
+ ",", true);
+
+ for (size_t i = 0; i < insert_into.size(); i++) {
+ {
+ google::protobuf::GeneratedCodeInfo info;
+ std::string content =
+ GetOutputFileContent(name_, "first_insert", file, context);
+ if (insert_endlines) {
+ GlobalReplaceSubstring(",", ",\n", &content);
+ }
+ if (annotate) {
+ auto* annotation = info.add_annotation();
+ annotation->set_begin(0);
+ annotation->set_end(content.size());
+ annotation->set_source_file("first_path");
+ }
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->OpenForInsertWithGeneratedCodeInfo(
+ GetOutputFileName(insert_into[i], file),
+ kFirstInsertionPointName, info));
+ io::Printer printer(output.get(), '$');
+ printer.PrintRaw(content);
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ }
+
+ {
+ google::protobuf::GeneratedCodeInfo info;
+ std::string content =
+ GetOutputFileContent(name_, "second_insert", file, context);
+ if (insert_endlines) {
+ GlobalReplaceSubstring(",", ",\n", &content);
+ }
+ if (annotate) {
+ auto* annotation = info.add_annotation();
+ annotation->set_begin(0);
+ annotation->set_end(content.size());
+ annotation->set_source_file("second_path");
+ }
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->OpenForInsertWithGeneratedCodeInfo(
+ GetOutputFileName(insert_into[i], file),
+ kSecondInsertionPointName, info));
+ io::Printer printer(output.get(), '$');
+ printer.PrintRaw(content);
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ }
+ }
+ } else {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(GetOutputFileName(name_, file)));
+
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(output.get(), '$',
+ annotate ? &annotation_collector : NULL);
+ printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context));
+ std::string annotate_suffix = "_annotation";
+ if (annotate) {
+ printer.Print("$p$\n", "p", "first");
+ printer.Annotate("p", "first" + annotate_suffix);
+ }
+ printer.PrintRaw(kFirstInsertionPoint);
+ if (annotate) {
+ printer.Print("$p$\n", "p", "second");
+ printer.Annotate("p", "second" + annotate_suffix);
+ }
+ printer.PrintRaw(kSecondInsertionPoint);
+ if (annotate) {
+ printer.Print("$p$\n", "p", "third");
+ printer.Annotate("p", "third" + annotate_suffix);
+ }
+
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ if (annotate) {
+ std::unique_ptr<io::ZeroCopyOutputStream> meta_output(
+ context->Open(GetOutputFileName(name_, file) + ".pb.meta"));
+ if (!TextFormat::Print(annotations, meta_output.get())) {
+ *error = "MockCodeGenerator couldn't write .pb.meta";
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+std::string MockCodeGenerator::GetOutputFileName(
+ const std::string& generator_name, const FileDescriptor* file) {
+ return GetOutputFileName(generator_name, file->name());
+}
+
+std::string MockCodeGenerator::GetOutputFileName(
+ const std::string& generator_name, const std::string& file) {
+ return file + ".MockCodeGenerator." + generator_name;
+}
+
+std::string MockCodeGenerator::GetOutputFileContent(
+ const std::string& generator_name, const std::string& parameter,
+ const FileDescriptor* file, GeneratorContext* context) {
+ std::vector<const FileDescriptor*> all_files;
+ context->ListParsedFiles(&all_files);
+ return GetOutputFileContent(
+ generator_name, parameter, file->name(), CommaSeparatedList(all_files),
+ file->message_type_count() > 0 ? file->message_type(0)->name()
+ : "(none)");
+}
+
+std::string MockCodeGenerator::GetOutputFileContent(
+ const std::string& generator_name, const std::string& parameter,
+ const std::string& file, const std::string& parsed_file_list,
+ const std::string& first_message_name) {
+ return strings::Substitute("$0: $1, $2, $3, $4\n", generator_name, parameter,
+ file, first_message_name, parsed_file_list);
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.h
new file mode 100644
index 00000000..4b7c4dd1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/mock_code_generator.h
@@ -0,0 +1,136 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+
+#include <cstdint>
+#include <string>
+
+#include <compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor;
+} // namespace protobuf
+} // namespace google
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// A mock CodeGenerator, used by command_line_interface_unittest. This is in
+// its own file so that it can be used both directly and as a plugin.
+//
+// Generate() produces some output which can be checked by ExpectCalled(). The
+// generator can run in a different process (e.g. a plugin).
+//
+// If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines
+// into the files generated by other MockCodeGenerators instead of creating
+// its own file. NAMES is a comma-separated list of the names of those other
+// MockCodeGenerators. If the parameter is "insert_endlines=NAMES", the
+// MockCodeGenerator will insert data guaranteed to contain more than one
+// endline into the files generated by NAMES.
+//
+// MockCodeGenerator will also modify its behavior slightly if the input file
+// contains a message type with one of the following names:
+// MockCodeGenerator_Error: Causes Generate() to return false and set the
+// error message to "Saw message type MockCodeGenerator_Error."
+// MockCodeGenerator_Exit: Generate() prints "Saw message type
+// MockCodeGenerator_Exit." to stderr and then calls exit(123).
+// MockCodeGenerator_Abort: Generate() prints "Saw message type
+// MockCodeGenerator_Abort." to stderr and then calls abort().
+// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after
+// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
+// stderr, where FOO is "1" if the supplied FileDescriptorProto has source
+// code info, and "0" otherwise.
+// MockCodeGenerator_Annotate: Generate() will add annotations to its output
+// that can later be verified with CheckGeneratedAnnotations.
+class MockCodeGenerator : public CodeGenerator {
+ public:
+ MockCodeGenerator(const std::string& name);
+ virtual ~MockCodeGenerator();
+
+ // Expect (via gTest) that a MockCodeGenerator with the given name was called
+ // with the given parameters by inspecting the output location.
+ //
+ // |insertions| is a comma-separated list of names of MockCodeGenerators which
+ // should have inserted lines into this file.
+ // |parsed_file_list| is a comma-separated list of names of the files
+ // that are being compiled together in this run.
+ static void ExpectGenerated(const std::string& name,
+ const std::string& parameter,
+ const std::string& insertions,
+ const std::string& file,
+ const std::string& first_message_name,
+ const std::string& parsed_file_list,
+ const std::string& output_directory);
+
+ // Checks that the correct text ranges were annotated by the
+ // MockCodeGenerator_Annotate directive.
+ static void CheckGeneratedAnnotations(const std::string& name,
+ const std::string& file,
+ const std::string& output_directory);
+
+ // Get the name of the file which would be written by the given generator.
+ static std::string GetOutputFileName(const std::string& generator_name,
+ const FileDescriptor* file);
+ static std::string GetOutputFileName(const std::string& generator_name,
+ const std::string& file);
+
+ // implements CodeGenerator ----------------------------------------
+
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override;
+ void SuppressFeatures(uint64_t features);
+
+ private:
+ std::string name_;
+ uint64_t suppressed_features_ = 0;
+
+ static std::string GetOutputFileContent(const std::string& generator_name,
+ const std::string& parameter,
+ const FileDescriptor* file,
+ GeneratorContext* context);
+ static std::string GetOutputFileContent(
+ const std::string& generator_name, const std::string& parameter,
+ const std::string& file, const std::string& parsed_file_list,
+ const std::string& first_message_name);
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc
new file mode 100644
index 00000000..5510750a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -0,0 +1,260 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_enum.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+#include <algorithm> // std::find()
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
+ : descriptor_(descriptor),
+ name_(EnumName(descriptor_)) {
+ // Track the names for the enum values, and if an alias overlaps a base
+ // value, skip making a name for it. Likewise if two alias overlap, the
+ // first one wins.
+ // The one gap in this logic is if two base values overlap, but for that
+ // to happen you have to have "Foo" and "FOO" or "FOO_BAR" and "FooBar",
+ // and if an enum has that, it is already going to be confusing and a
+ // compile error is just fine.
+ // The values are still tracked to support the reflection apis and
+ // TextFormat handing since they are different there.
+ std::set<std::string> value_names;
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ base_values_.push_back(value);
+ value_names.insert(EnumValueName(value));
+ } else {
+ std::string value_name(EnumValueName(value));
+ if (value_names.find(value_name) != value_names.end()) {
+ alias_values_to_skip_.insert(value);
+ } else {
+ value_names.insert(value_name);
+ }
+ }
+ all_values_.push_back(value);
+ }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::GenerateHeader(io::Printer* printer) {
+ std::string enum_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ enum_comments = BuildCommentsString(location, true);
+ } else {
+ enum_comments = "";
+ }
+
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ // Swift 5 included SE0192 "Handling Future Enum Cases"
+ // https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
+ // Since a .proto file can get new values added to an enum at any time, they
+ // are effectively "non-frozen". Even in a proto3 syntax file where there is
+ // support for the unknown value, an edit to the file can always add a new
+ // value moving something from unknown to known. Since Swift is now ABI
+ // stable, it also means a binary could contain Swift compiled against one
+ // version of the .pbobjc.h file, but finally linked against an enum with
+ // more cases. So the Swift code will always have to treat ObjC Proto Enums
+ // as "non-frozen". The default behavior in SE0192 is for all objc enums to
+ // be "non-frozen" unless marked as otherwise, so this means this generation
+ // doesn't have to bother with the `enum_extensibility` attribute, as the
+ // default will be what is needed.
+
+ printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
+ "comments", enum_comments,
+ "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()),
+ "name", name_);
+ printer->Indent();
+
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ // Include the unknown value.
+ printer->Print(
+ "/**\n"
+ " * Value used if any message's field encounters a value that is not defined\n"
+ " * by this enum. The message will also have C functions to get/set the rawValue\n"
+ " * of the field.\n"
+ " **/\n"
+ "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
+ "name", name_);
+ }
+ for (int i = 0; i < all_values_.size(); i++) {
+ if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) {
+ continue;
+ }
+ if (all_values_[i]->GetSourceLocation(&location)) {
+ std::string comments = BuildCommentsString(location, true).c_str();
+ if (comments.length() > 0) {
+ if (i > 0) {
+ printer->Print("\n");
+ }
+ printer->Print(comments.c_str());
+ }
+ }
+
+ printer->Print(
+ "$name$$deprecated_attribute$ = $value$,\n",
+ "name", EnumValueName(all_values_[i]),
+ "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
+ "value", StrCat(all_values_[i]->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n"
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
+ "\n"
+ "/**\n"
+ " * Checks to see if the given value is defined by the enum or was not known at\n"
+ " * the time this source was generated.\n"
+ " **/\n"
+ "BOOL $name$_IsValidValue(int32_t value);\n"
+ "\n",
+ "name", name_);
+}
+
+void EnumGenerator::GenerateSource(io::Printer* printer) {
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ // Note: For the TextFormat decode info, we can't use the enum value as
+ // the key because protocol buffer enums have 'allow_alias', which lets
+ // a value be used more than once. Instead, the index into the list of
+ // enum value descriptions is used. Note: start with -1 so the first one
+ // will be zero.
+ TextFormatDecodeData text_format_decode_data;
+ int enum_value_description_key = -1;
+ std::string text_blob;
+
+ for (int i = 0; i < all_values_.size(); i++) {
+ ++enum_value_description_key;
+ std::string short_name(EnumValueShortName(all_values_[i]));
+ text_blob += short_name + '\0';
+ if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
+ text_format_decode_data.AddString(enum_value_description_key, short_name,
+ all_values_[i]->name());
+ }
+ }
+
+ printer->Print(
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+ " static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n"
+ " if (!descriptor) {\n",
+ "name", name_);
+
+ static const int kBytesPerLine = 40; // allow for escaping
+ printer->Print(
+ " static const char *valueNames =");
+ for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
+ printer->Print(
+ "\n \"$data$\"",
+ "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine))));
+ }
+ printer->Print(
+ ";\n"
+ " static const int32_t values[] = {\n");
+ for (int i = 0; i < all_values_.size(); i++) {
+ printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i]));
+ }
+ printer->Print(" };\n");
+
+ if (text_format_decode_data.num_entries() == 0) {
+ printer->Print(
+ " GPBEnumDescriptor *worker =\n"
+ " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " valueNames:valueNames\n"
+ " values:values\n"
+ " count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+ " enumVerifier:$name$_IsValidValue];\n",
+ "name", name_);
+ } else {
+ printer->Print(
+ " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+ " GPBEnumDescriptor *worker =\n"
+ " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " valueNames:valueNames\n"
+ " values:values\n"
+ " count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+ " enumVerifier:$name$_IsValidValue\n"
+ " extraTextFormatInfo:extraTextFormatInfo];\n",
+ "name", name_,
+ "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+ }
+ printer->Print(
+ " GPBEnumDescriptor *expected = nil;\n"
+ " if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
+ " [worker release];\n"
+ " }\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n");
+
+ printer->Print(
+ "BOOL $name$_IsValidValue(int32_t value__) {\n"
+ " switch (value__) {\n",
+ "name", name_);
+
+ for (int i = 0; i < base_values_.size(); i++) {
+ printer->Print(
+ " case $name$:\n",
+ "name", EnumValueName(base_values_[i]));
+ }
+
+ printer->Print(
+ " return YES;\n"
+ " default:\n"
+ " return NO;\n"
+ " }\n"
+ "}\n\n");
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h
new file mode 100644
index 00000000..51560dd1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator {
+ public:
+ explicit EnumGenerator(const EnumDescriptor* descriptor);
+ ~EnumGenerator();
+
+ EnumGenerator(const EnumGenerator&) = delete;
+ EnumGenerator& operator=(const EnumGenerator&) = delete;
+
+ void GenerateHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+
+ const std::string& name() const { return name_; }
+
+ private:
+ const EnumDescriptor* descriptor_;
+ std::vector<const EnumValueDescriptor*> base_values_;
+ std::vector<const EnumValueDescriptor*> all_values_;
+ std::set<const EnumValueDescriptor*> alias_values_to_skip_;
+ const std::string name_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc
new file mode 100644
index 00000000..66877afb
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -0,0 +1,149 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_enum_field.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+#include <wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetEnumVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ std::string type = EnumName(descriptor->enum_type());
+ (*variables)["storage_type"] = type;
+ // For non repeated fields, if it was defined in a different file, the
+ // property decls need to use "enum NAME" rather than just "NAME" to support
+ // the forward declaration of the enums.
+ if (!descriptor->is_repeated() &&
+ (descriptor->file() != descriptor->enum_type()->file())) {
+ (*variables)["property_type"] = "enum " + type;
+ }
+ (*variables)["enum_verifier"] = type + "_IsValidValue";
+ (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
+
+ (*variables)["dataTypeSpecific_name"] = "enumDescFunc";
+ (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"];
+
+ const Descriptor* msg_descriptor = descriptor->containing_type();
+ (*variables)["owning_message_class"] = ClassName(msg_descriptor);
+}
+} // namespace
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
+ SetEnumVariables(descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ return;
+ }
+
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
+ " * if the value was not defined by the enum at the time the code was generated.\n"
+ " **/\n"
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
+ "/**\n"
+ " * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
+ " * it to be set to a value that was not defined by the enum at the time the code\n"
+ " * was generated.\n"
+ " **/\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
+ "\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+
+ printer->Print(
+ variables_,
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " return GPBGetMessageRawEnumField(message, field);\n"
+ "}\n"
+ "\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " GPBSetMessageRawEnumField(message, field, value);\n"
+ "}\n"
+ "\n");
+}
+
+void EnumFieldGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const {
+ SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ // If it is an enum defined in a different file, then we'll need a forward
+ // declaration for it. When it is in our file, all the enums are output
+ // before the message, so it will be declared before it is needed.
+ if (descriptor_->file() != descriptor_->enum_type()->file()) {
+ // Enum name is already in "storage_type".
+ const std::string& name = variable("storage_type");
+ fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
+ }
+}
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
+ SetEnumVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "GPBEnumArray";
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h
new file mode 100644
index 00000000..1f11abcb
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ EnumFieldGenerator(const EnumFieldGenerator&) = delete;
+ EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
+
+ public:
+ virtual void GenerateCFunctionDeclarations(
+ io::Printer* printer) const override;
+ virtual void GenerateCFunctionImplementations(
+ io::Printer* printer) const override;
+ virtual void DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const override;
+
+ protected:
+ EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+ virtual ~EnumFieldGenerator();
+};
+
+class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ public:
+ virtual void FinishInitialization() override;
+
+ protected:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual ~RepeatedEnumFieldGenerator();
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc
new file mode 100644
index 00000000..7ec80bc9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -0,0 +1,156 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include <compiler/objectivec/objectivec_extension.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <descriptor.pb.h>
+#include <stubs/strutil.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ExtensionGenerator::ExtensionGenerator(const std::string& root_class_name,
+ const FieldDescriptor* descriptor)
+ : method_name_(ExtensionMethodName(descriptor)),
+ root_class_and_method_name_(root_class_name + "_" + method_name_),
+ descriptor_(descriptor) {
+ if (descriptor->is_map()) {
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error cases, so it seems to be ok to use as a back door for errors.
+ std::cerr << "error: Extension is a map<>!"
+ << " That used to be blocked by the compiler." << std::endl;
+ std::cerr.flush();
+ abort();
+ }
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["method_name"] = method_name_;
+ if (IsRetainedName(method_name_)) {
+ vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
+ } else {
+ vars["storage_attribute"] = "";
+ }
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ vars["comments"] = BuildCommentsString(location, true);
+ } else {
+ vars["comments"] = "";
+ }
+ // Unlike normal message fields, check if the file for the extension was
+ // deprecated.
+ vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
+ printer->Print(vars,
+ "$comments$"
+ "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
+}
+
+void ExtensionGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer) {
+ std::map<std::string, std::string> vars;
+ vars["root_class_and_method_name"] = root_class_and_method_name_;
+ const std::string containing_type = ClassName(descriptor_->containing_type());
+ vars["extended_type"] = ObjCClass(containing_type);
+ vars["number"] = StrCat(descriptor_->number());
+
+ std::vector<std::string> options;
+ if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
+ if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
+ if (descriptor_->containing_type()->options().message_set_wire_format()) {
+ options.push_back("GPBExtensionSetWireFormat");
+ }
+ vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
+
+ ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+ if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+ std::string message_type = ClassName(descriptor_->message_type());
+ vars["type"] = ObjCClass(message_type);
+ } else {
+ vars["type"] = "Nil";
+ }
+
+ vars["default_name"] = GPBGenericValueFieldName(descriptor_);
+ if (descriptor_->is_repeated()) {
+ vars["default"] = "nil";
+ } else {
+ vars["default"] = DefaultValue(descriptor_);
+ }
+ std::string type = GetCapitalizedType(descriptor_);
+ vars["extension_type"] = std::string("GPBDataType") + type;
+
+ if (objc_type == OBJECTIVECTYPE_ENUM) {
+ vars["enum_desc_func_name"] =
+ EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
+ } else {
+ vars["enum_desc_func_name"] = "NULL";
+ }
+
+ printer->Print(vars,
+ "{\n"
+ " .defaultValue.$default_name$ = $default$,\n"
+ " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+ " .extendedClass.clazz = $extended_type$,\n"
+ " .messageOrGroupClass.clazz = $type$,\n"
+ " .enumDescriptorFunc = $enum_desc_func_name$,\n"
+ " .fieldNumber = $number$,\n"
+ " .dataType = $extension_type$,\n"
+ " .options = $options$,\n"
+ "},\n");
+}
+
+void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) {
+ std::string extended_type = ClassName(descriptor_->containing_type());
+ fwd_decls->insert(ObjCClassDeclaration(extended_type));
+ ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+ if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+ std::string message_type = ClassName(descriptor_->message_type());
+ fwd_decls->insert(ObjCClassDeclaration(message_type));
+ }
+}
+
+void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
+ printer->Print(
+ "[registry addExtension:$root_class_and_method_name$];\n",
+ "root_class_and_method_name", root_class_and_method_name_);
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h
new file mode 100644
index 00000000..b985d831
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator {
+ public:
+ ExtensionGenerator(const std::string& root_class_name,
+ const FieldDescriptor* descriptor);
+ ~ExtensionGenerator();
+
+ ExtensionGenerator(const ExtensionGenerator&) = delete;
+ ExtensionGenerator& operator=(const ExtensionGenerator&) = delete;
+
+ void GenerateMembersHeader(io::Printer* printer);
+ void GenerateStaticVariablesInitialization(io::Printer* printer);
+ void GenerateRegistrationSource(io::Printer* printer);
+ void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
+
+ private:
+ std::string method_name_;
+ std::string root_class_and_method_name_;
+ const FieldDescriptor* descriptor_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc
new file mode 100644
index 00000000..29f434b5
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc
@@ -0,0 +1,475 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include <compiler/objectivec/objectivec_field.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <compiler/objectivec/objectivec_enum_field.h>
+#include <compiler/objectivec/objectivec_map_field.h>
+#include <compiler/objectivec/objectivec_message_field.h>
+#include <compiler/objectivec/objectivec_primitive_field.h>
+#include <io/printer.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ std::string camel_case_name = FieldName(descriptor);
+ std::string raw_field_name;
+ if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+ raw_field_name = descriptor->message_type()->name();
+ } else {
+ raw_field_name = descriptor->name();
+ }
+ // The logic here has to match -[GGPBFieldDescriptor textFormatName].
+ const std::string un_camel_case_name(
+ UnCamelCaseFieldName(camel_case_name, descriptor));
+ const bool needs_custom_name = (raw_field_name != un_camel_case_name);
+
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ (*variables)["comments"] = BuildCommentsString(location, true);
+ } else {
+ (*variables)["comments"] = "\n";
+ }
+ const std::string& classname = ClassName(descriptor->containing_type());
+ (*variables)["classname"] = classname;
+ (*variables)["name"] = camel_case_name;
+ const std::string& capitalized_name = FieldNameCapitalized(descriptor);
+ (*variables)["capitalized_name"] = capitalized_name;
+ (*variables)["raw_field_name"] = raw_field_name;
+ (*variables)["field_number_name"] =
+ classname + "_FieldNumber_" + capitalized_name;
+ (*variables)["field_number"] = StrCat(descriptor->number());
+ (*variables)["field_type"] = GetCapitalizedType(descriptor);
+ (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
+ std::vector<std::string> field_flags;
+ if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
+ if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
+ if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
+ if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
+
+ // ObjC custom flags.
+ if (descriptor->has_default_value())
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
+ if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+ // It will clear on a zero value if...
+ // - not repeated/map
+ // - doesn't have presence
+ bool clear_on_zero =
+ (!descriptor->is_repeated() && !descriptor->has_presence());
+ if (clear_on_zero) {
+ field_flags.push_back("GPBFieldClearHasIvarOnZero");
+ }
+
+ (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
+
+ (*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
+
+ (*variables)["dataTypeSpecific_name"] = "clazz";
+ (*variables)["dataTypeSpecific_value"] = "Nil";
+
+ (*variables)["storage_offset_value"] =
+ "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
+ (*variables)["storage_offset_comment"] = "";
+
+ // Clear some common things so they can be set just when needed.
+ (*variables)["storage_attribute"] = "";
+}
+
+} // namespace
+
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options) {
+ FieldGenerator* result = NULL;
+ if (field->is_repeated()) {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ if (field->is_map()) {
+ result = new MapFieldGenerator(field, options);
+ } else {
+ result = new RepeatedMessageFieldGenerator(field, options);
+ }
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new RepeatedEnumFieldGenerator(field, options);
+ break;
+ default:
+ result = new RepeatedPrimitiveFieldGenerator(field, options);
+ break;
+ }
+ } else {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ result = new MessageFieldGenerator(field, options);
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new EnumFieldGenerator(field, options);
+ break;
+ default:
+ if (IsReferenceType(field)) {
+ result = new PrimitiveObjFieldGenerator(field, options);
+ } else {
+ result = new PrimitiveFieldGenerator(field, options);
+ }
+ break;
+ }
+ }
+ result->FinishInitialization();
+ return result;
+}
+
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : descriptor_(descriptor) {
+ SetCommonFieldVariables(descriptor, &variables_);
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$field_number_name$ = $field_number$,\n");
+}
+
+void FieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const {
+ // Nothing
+}
+
+void FieldGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateFieldDescription(
+ io::Printer* printer, bool include_default) const {
+ // Printed in the same order as the structure decl.
+ if (include_default) {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .defaultValue.$default_name$ = $default$,\n"
+ " .core.name = \"$name$\",\n"
+ " .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+ " .core.number = $field_number_name$,\n"
+ " .core.hasIndex = $has_index$,\n"
+ " .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
+ " .core.flags = $fieldflags$,\n"
+ " .core.dataType = GPBDataType$field_type$,\n"
+ "},\n");
+ } else {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+ " .number = $field_number_name$,\n"
+ " .hasIndex = $has_index$,\n"
+ " .offset = $storage_offset_value$,$storage_offset_comment$\n"
+ " .flags = $fieldflags$,\n"
+ " .dataType = GPBDataType$field_type$,\n"
+ "},\n");
+ }
+}
+
+void FieldGenerator::SetRuntimeHasBit(int has_index) {
+ variables_["has_index"] = StrCat(has_index);
+}
+
+void FieldGenerator::SetNoHasBit(void) {
+ variables_["has_index"] = "GPBNoHasBit";
+}
+
+int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+ return 0;
+}
+
+void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error cases, so it seems to be ok to use as a back door for errors.
+ std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
+ std::cerr.flush();
+ abort();
+}
+
+void FieldGenerator::SetOneofIndexBase(int index_base) {
+ const OneofDescriptor* oneof = descriptor_->real_containing_oneof();
+ if (oneof != NULL) {
+ int index = oneof->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["has_index"] = StrCat(-index);
+ }
+}
+
+bool FieldGenerator::WantsHasProperty(void) const {
+ return descriptor_->has_presence() && !descriptor_->real_containing_oneof();
+}
+
+void FieldGenerator::FinishInitialization(void) {
+ // If "property_type" wasn't set, make it "storage_type".
+ if ((variables_.find("property_type") == variables_.end()) &&
+ (variables_.find("storage_type") != variables_.end())) {
+ variables_["property_type"] = variable("storage_type");
+ }
+}
+
+SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(descriptor, options) {
+ // Nothing
+}
+
+SingleFieldGenerator::~SingleFieldGenerator() {}
+
+void SingleFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ $name$;\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$comments$");
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
+ "\n");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+ }
+}
+
+void SingleFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ if (WantsHasProperty()) {
+ printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
+ } else {
+ printer->Print(variables_, "@dynamic $name$;\n");
+ }
+}
+
+bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+ if (descriptor_->real_containing_oneof()) {
+ // The oneof tracks what is set instead.
+ return false;
+ }
+ return true;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
+ variables_["property_storage_attribute"] = "strong";
+ if (IsRetainedName(variables_["name"])) {
+ variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
+ }
+}
+
+ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
+
+void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ *$name$;\n");
+}
+
+void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
+ // it uses pointers and deals with Objective C's rules around storage name
+ // conventions (init*, new*, etc.)
+
+ printer->Print(variables_, "$comments$");
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "/** Test to see if @c $name$ has been set. */\n"
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+ }
+ if (IsInitName(variables_.find("name")->second)) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+ }
+ printer->Print("\n");
+}
+
+RepeatedFieldGenerator::RepeatedFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
+ // Default to no comment and let the cases needing it fill it in.
+ variables_["array_comment"] = "";
+}
+
+RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
+
+void RepeatedFieldGenerator::FinishInitialization(void) {
+ FieldGenerator::FinishInitialization();
+ if (variables_.find("array_property_type") == variables_.end()) {
+ variables_["array_property_type"] = variable("array_storage_type");
+ }
+}
+
+void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$array_storage_type$ *$name$;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ printer->Print(variables_, "@dynamic $name$, $name$_Count;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Repeated fields don't need the has* properties, but they do expose a
+ // *Count (to check without autocreation). So for the field property we need
+ // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
+ // dealing with needing Objective C's rules around storage name conventions
+ // (init*, new*, etc.)
+
+ printer->Print(
+ variables_,
+ "$comments$"
+ "$array_comment$"
+ "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
+ "/** The number of items in @c $name$ without causing the array to be created. */\n"
+ "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
+ if (IsInitName(variables_.find("name")->second)) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+ }
+ printer->Print("\n");
+}
+
+bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+ return false; // The array (or map/dict) having anything is what is used.
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+ const Options& options)
+ : descriptor_(descriptor),
+ field_generators_(descriptor->field_count()),
+ extension_generators_(descriptor->extension_count()) {
+ // Construct all the FieldGenerators.
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ field_generators_[i].reset(
+ FieldGenerator::Make(descriptor->field(i), options));
+ }
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ extension_generators_[i].reset(
+ FieldGenerator::Make(descriptor->extension(i), options));
+ }
+}
+
+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];
+}
+
+int FieldGeneratorMap::CalculateHasBits(void) {
+ int total_bits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (field_generators_[i]->RuntimeUsesHasBit()) {
+ field_generators_[i]->SetRuntimeHasBit(total_bits);
+ ++total_bits;
+ } else {
+ field_generators_[i]->SetNoHasBit();
+ }
+ int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
+ if (extra_bits) {
+ field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
+ total_bits += extra_bits;
+ }
+ }
+ return total_bits;
+}
+
+void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_[i]->SetOneofIndexBase(index_base);
+ }
+}
+
+bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (HasNonZeroDefaultValue(descriptor_->field(i))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h
new file mode 100644
index 00000000..ee213ff4
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h
@@ -0,0 +1,194 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class FieldGenerator {
+ public:
+ static FieldGenerator* Make(const FieldDescriptor* field,
+ const Options& options);
+
+ virtual ~FieldGenerator();
+
+ FieldGenerator(const FieldGenerator&) = delete;
+ FieldGenerator& operator=(const FieldGenerator&) = delete;
+
+ // Exposed for subclasses to fill in.
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
+
+ // Called by GenerateFieldDescription, exposed for classes that need custom
+ // generation.
+
+ // Exposed for subclasses to extend, base does nothing.
+ virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+ virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+ // Exposed for subclasses, should always call it on the parent class also.
+ virtual void DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const;
+ virtual void DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const;
+
+ // Used during generation, not intended to be extended by subclasses.
+ void GenerateFieldDescription(
+ io::Printer* printer, bool include_default) const;
+ void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+ // Exposed to get and set the has bits information.
+ virtual bool RuntimeUsesHasBit(void) const = 0;
+ void SetRuntimeHasBit(int has_index);
+ void SetNoHasBit(void);
+ virtual int ExtraRuntimeHasBitsNeeded(void) const;
+ virtual void SetExtraRuntimeHasBitsBase(int index_base);
+ void SetOneofIndexBase(int index_base);
+
+ std::string variable(const char* key) const {
+ return variables_.find(key)->second;
+ }
+
+ bool needs_textformat_name_support() const {
+ const std::string& field_flags = variable("fieldflags");
+ return field_flags.find("GPBFieldTextFormatNameCustom") !=
+ std::string::npos;
+ }
+ std::string generated_objc_name() const { return variable("name"); }
+ std::string raw_field_name() const { return variable("raw_field_name"); }
+
+ protected:
+ FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+
+ virtual void FinishInitialization(void);
+ bool WantsHasProperty(void) const;
+
+ const FieldDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+};
+
+class SingleFieldGenerator : public FieldGenerator {
+ public:
+ virtual ~SingleFieldGenerator();
+
+ SingleFieldGenerator(const SingleFieldGenerator&) = delete;
+ SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete;
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
+
+ virtual bool RuntimeUsesHasBit(void) const override;
+
+ protected:
+ SingleFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+};
+
+// Subclass with common support for when the field ends up as an ObjC Object.
+class ObjCObjFieldGenerator : public SingleFieldGenerator {
+ public:
+ virtual ~ObjCObjFieldGenerator();
+
+ ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete;
+ ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete;
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+
+ protected:
+ ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+};
+
+class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
+ public:
+ virtual ~RepeatedFieldGenerator();
+
+ RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete;
+ RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete;
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
+
+ virtual bool RuntimeUsesHasBit(void) const override;
+
+ protected:
+ RepeatedFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual void FinishInitialization(void) override;
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+ FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+ ~FieldGeneratorMap();
+
+ FieldGeneratorMap(const FieldGeneratorMap&) = delete;
+ FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete;
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+ const FieldGenerator& get_extension(int index) const;
+
+ // Assigns the has bits and returns the number of bits needed.
+ int CalculateHasBits(void);
+
+ void SetOneofIndexBase(int index_base);
+
+ // Check if any field of this message has a non zero default.
+ bool DoesAnyFieldHaveNonZeroDefault(void) const;
+
+ private:
+ const Descriptor* descriptor_;
+ std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
+ std::vector<std::unique_ptr<FieldGenerator>> extension_generators_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc
new file mode 100644
index 00000000..e98a8985
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc
@@ -0,0 +1,610 @@
+// 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 <compiler/objectivec/objectivec_file.h>
+#include <compiler/objectivec/objectivec_enum.h>
+#include <compiler/objectivec/objectivec_extension.h>
+#include <compiler/objectivec/objectivec_message.h>
+#include <compiler/code_generator.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream_impl.h>
+#include <stubs/stl_util.h>
+#include <stubs/strutil.h>
+#include <algorithm> // std::find()
+#include <iostream>
+#include <sstream>
+
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error cases, so it seems to be ok to use as a back door for errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+// This is also found in GPBBootstrap.h, and needs to be kept in sync.
+const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30004;
+
+const char* kHeaderExtension = ".pbobjc.h";
+
+// Checks if a message contains any enums definitions (on the message or
+// a nested message under it).
+bool MessageContainsEnums(const Descriptor* message) {
+ if (message->enum_type_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ if (MessageContainsEnums(message->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Checks if a message contains any extension definitions (on the message or
+// a nested message under it).
+bool MessageContainsExtensions(const Descriptor* message) {
+ if (message->extension_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ if (MessageContainsExtensions(message->nested_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Checks if the file contains any enum definitions (at the root or
+// nested under a message).
+bool FileContainsEnums(const FileDescriptor* file) {
+ if (file->enum_type_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (MessageContainsEnums(file->message_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Checks if the file contains any extensions definitions (at the root or
+// nested under a message).
+bool FileContainsExtensions(const FileDescriptor* file) {
+ if (file->extension_count() > 0) {
+ return true;
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (MessageContainsExtensions(file->message_type(i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all
+// deps as visited and prunes them from the needed files list.
+void PruneFileAndDepsMarkingAsVisited(
+ const FileDescriptor* file,
+ std::vector<const FileDescriptor*>* files,
+ std::set<const FileDescriptor*>* files_visited) {
+ std::vector<const FileDescriptor*>::iterator iter =
+ std::find(files->begin(), files->end(), file);
+ if (iter != files->end()) {
+ files->erase(iter);
+ }
+ files_visited->insert(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited);
+ }
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensions.
+void CollectMinimalFileDepsContainingExtensionsWorker(
+ const FileDescriptor* file,
+ std::vector<const FileDescriptor*>* files,
+ std::set<const FileDescriptor*>* files_visited) {
+ if (files_visited->find(file) != files_visited->end()) {
+ return;
+ }
+ files_visited->insert(file);
+
+ if (FileContainsExtensions(file)) {
+ files->push_back(file);
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
+ }
+ } else {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ files_visited);
+ }
+ }
+}
+
+// Collect the deps of the given file that contain extensions. This can be used to
+// create the chain of roots that need to be wired together.
+//
+// NOTE: If any changes are made to this and the supporting functions, you will
+// need to manually validate what the generated code is for the test files:
+// objectivec/Tests/unittest_extension_chain_*.proto
+// There are comments about what the expected code should be line and limited
+// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
+// specifically).
+void CollectMinimalFileDepsContainingExtensions(
+ const FileDescriptor* file,
+ std::vector<const FileDescriptor*>* files) {
+ std::set<const FileDescriptor*> files_visited;
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dep = file->dependency(i);
+ CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+ &files_visited);
+ }
+}
+
+bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ if (dep == file->dependency(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
+ : file_(file),
+ root_class_name_(FileClassName(file)),
+ is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)),
+ options_(options) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator* generator = new EnumGenerator(file_->enum_type(i));
+ enum_generators_.emplace_back(generator);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator* generator =
+ new MessageGenerator(root_class_name_, file_->message_type(i), options_);
+ message_generators_.emplace_back(generator);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator* generator =
+ new ExtensionGenerator(root_class_name_, file_->extension(i));
+ extension_generators_.emplace_back(generator);
+ }
+}
+
+FileGenerator::~FileGenerator() {}
+
+void FileGenerator::GenerateHeader(io::Printer* printer) {
+ std::vector<std::string> headers;
+ // Generated files bundled with the library get minimal imports, everything
+ // else gets the wrapper so everything is usable.
+ if (is_bundled_proto_) {
+ headers.push_back("GPBDescriptor.h");
+ headers.push_back("GPBMessage.h");
+ headers.push_back("GPBRootObject.h");
+ } else {
+ headers.push_back("GPBProtocolBuffers.h");
+ }
+ PrintFileRuntimePreamble(printer, headers);
+
+ // Add some verification that the generated code matches the source the
+ // code is being compiled with.
+ // NOTE: This captures the raw numeric values at the time the generator was
+ // compiled, since that will be the versions for the ObjC runtime at that
+ // time. The constants in the generated code will then get their values at
+ // at compile time (so checking against the headers being used to compile).
+ printer->Print(
+ "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
+ "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+ "#endif\n"
+ "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
+ "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+ "#endif\n"
+ "\n",
+ "google_protobuf_objc_version", StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
+
+ // #import any headers for "public imports" in the proto file.
+ {
+ ImportWriter import_writer(
+ options_.generate_for_named_framework,
+ options_.named_framework_to_proto_path_mappings_path,
+ options_.runtime_import_prefix,
+ is_bundled_proto_);
+ const std::string header_extension(kHeaderExtension);
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ import_writer.AddFile(file_->public_dependency(i), header_extension);
+ }
+ import_writer.Print(printer);
+ }
+
+ // Note:
+ // deprecated-declarations suppression is only needed if some place in this
+ // proto file is something deprecated or if it references something from
+ // another file that is deprecated.
+ printer->Print(
+ "// @@protoc_insertion_point(imports)\n"
+ "\n"
+ "#pragma clang diagnostic push\n"
+ "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
+ "\n"
+ "CF_EXTERN_C_BEGIN\n"
+ "\n");
+
+ std::set<std::string> fwd_decls;
+ for (const auto& generator : message_generators_) {
+ generator->DetermineForwardDeclarations(&fwd_decls);
+ }
+ for (std::set<std::string>::const_iterator i(fwd_decls.begin());
+ i != fwd_decls.end(); ++i) {
+ printer->Print("$value$;\n", "value", *i);
+ }
+ if (fwd_decls.begin() != fwd_decls.end()) {
+ printer->Print("\n");
+ }
+
+ printer->Print(
+ "NS_ASSUME_NONNULL_BEGIN\n"
+ "\n");
+
+ // need to write out all enums first
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateHeader(printer);
+ }
+
+ for (const auto& generator : message_generators_) {
+ generator->GenerateEnumHeader(printer);
+ }
+
+ // For extensions to chain together, the Root gets created even if there
+ // are no extensions.
+ printer->Print(
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "/**\n"
+ " * Exposes the extension registry for this file.\n"
+ " *\n"
+ " * The base class provides:\n"
+ " * @code\n"
+ " * + (GPBExtensionRegistry *)extensionRegistry;\n"
+ " * @endcode\n"
+ " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
+ " * this file and all files that it depends on.\n"
+ " **/\n"
+ "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
+ "@end\n"
+ "\n",
+ "root_class_name", root_class_name_);
+
+ if (!extension_generators_.empty()) {
+ // The dynamic methods block is only needed if there are extensions.
+ printer->Print(
+ "@interface $root_class_name$ (DynamicMethods)\n",
+ "root_class_name", root_class_name_);
+
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateMembersHeader(printer);
+ }
+
+ printer->Print("@end\n\n");
+ } // !extension_generators_.empty()
+
+ for (const auto& generator : message_generators_) {
+ generator->GenerateMessageHeader(printer);
+ }
+
+ printer->Print(
+ "NS_ASSUME_NONNULL_END\n"
+ "\n"
+ "CF_EXTERN_C_END\n"
+ "\n"
+ "#pragma clang diagnostic pop\n"
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateSource(io::Printer* printer) {
+ // #import the runtime support.
+ std::vector<std::string> headers;
+ headers.push_back("GPBProtocolBuffers_RuntimeSupport.h");
+ PrintFileRuntimePreamble(printer, headers);
+
+ // Enums use atomic in the generated code, so add the system import as needed.
+ if (FileContainsEnums(file_)) {
+ printer->Print(
+ "#import <stdatomic.h>\n"
+ "\n");
+ }
+
+ std::vector<const FileDescriptor*> deps_with_extensions;
+ CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions);
+
+ {
+ ImportWriter import_writer(
+ options_.generate_for_named_framework,
+ options_.named_framework_to_proto_path_mappings_path,
+ options_.runtime_import_prefix,
+ is_bundled_proto_);
+ const std::string header_extension(kHeaderExtension);
+
+ // #import the header for this proto file.
+ import_writer.AddFile(file_, header_extension);
+
+ // #import the headers for anything that a plain dependency of this proto
+ // file (that means they were just an include, not a "public" include).
+ std::set<std::string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const FileDescriptor *dep = file_->dependency(i);
+ bool public_import = (public_import_names.count(dep->name()) != 0);
+ if (!public_import) {
+ import_writer.AddFile(dep, header_extension);
+ }
+ }
+
+ // If any indirect dependency provided extensions, it needs to be directly
+ // imported so it can get merged into the root's extensions registry.
+ // See the Note by CollectMinimalFileDepsContainingExtensions before
+ // changing this.
+ for (std::vector<const FileDescriptor*>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ if (!IsDirectDependency(*iter, file_)) {
+ import_writer.AddFile(*iter, header_extension);
+ }
+ }
+
+ import_writer.Print(printer);
+ }
+
+ bool includes_oneof = false;
+ for (const auto& generator : message_generators_) {
+ if (generator->IncludesOneOfDefinition()) {
+ includes_oneof = true;
+ break;
+ }
+ }
+
+ std::set<std::string> fwd_decls;
+ for (const auto& generator : message_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
+ }
+ for (const auto& generator : extension_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
+ }
+
+ // Note:
+ // deprecated-declarations suppression is only needed if some place in this
+ // proto file is something deprecated or if it references something from
+ // another file that is deprecated.
+ // dollar-in-identifier-extension is needed because we use references to
+ // objc class names that have $ in identifiers.
+ printer->Print(
+ "// @@protoc_insertion_point(imports)\n"
+ "\n"
+ "#pragma clang diagnostic push\n"
+ "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
+ if (includes_oneof) {
+ // The generated code for oneof's uses direct ivar access, suppress the
+ // warning in case developer turn that on in the context they compile the
+ // generated code.
+ printer->Print(
+ "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
+ }
+ if (!fwd_decls.empty()) {
+ printer->Print(
+ "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n");
+ }
+ printer->Print(
+ "\n");
+ if (!fwd_decls.empty()) {
+ printer->Print(
+ "#pragma mark - Objective C Class declarations\n"
+ "// Forward declarations of Objective C classes that we can use as\n"
+ "// static values in struct initializers.\n"
+ "// We don't use [Foo class] because it is not a static value.\n");
+ }
+ for (const auto& i : fwd_decls) {
+ printer->Print("$value$\n", "value", i);
+ }
+ if (!fwd_decls.empty()) {
+ printer->Print("\n");
+ }
+ printer->Print(
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "@implementation $root_class_name$\n\n",
+ "root_class_name", root_class_name_);
+
+ const bool file_contains_extensions = FileContainsExtensions(file_);
+
+ // If there were any extensions or this file has any dependencies, output
+ // a registry to override to create the file specific registry.
+ if (file_contains_extensions || !deps_with_extensions.empty()) {
+ printer->Print(
+ "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety and initialization of registry.\n"
+ " static GPBExtensionRegistry* registry = nil;\n"
+ " if (!registry) {\n"
+ " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
+ " registry = [[GPBExtensionRegistry alloc] init];\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ if (file_contains_extensions) {
+ printer->Print(
+ "static GPBExtensionDescription descriptions[] = {\n");
+ printer->Indent();
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+ for (const auto& generator : message_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+ " GPBExtensionDescriptor *extension =\n"
+ " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
+ " usesClassRefs:YES];\n"
+ " [registry addExtension:extension];\n"
+ " [self globallyRegisterExtension:extension];\n"
+ " [extension release];\n"
+ "}\n");
+ }
+
+ if (deps_with_extensions.empty()) {
+ printer->Print(
+ "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
+ "// them to this registry.\n");
+ } else {
+ printer->Print(
+ "// Merge in the imports (direct or indirect) that defined extensions.\n");
+ for (std::vector<const FileDescriptor*>::iterator iter =
+ deps_with_extensions.begin();
+ iter != deps_with_extensions.end(); ++iter) {
+ const std::string root_class_name(FileClassName((*iter)));
+ printer->Print(
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+ "dependency", root_class_name);
+ }
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ " return registry;\n"
+ "}\n");
+ } else {
+ if (file_->dependency_count() > 0) {
+ printer->Print(
+ "// No extensions in the file and none of the imports (direct or indirect)\n"
+ "// defined extensions, so no need to generate +extensionRegistry.\n");
+ } else {
+ printer->Print(
+ "// No extensions in the file and no imports, so no need to generate\n"
+ "// +extensionRegistry.\n");
+ }
+ }
+
+ printer->Print("\n@end\n\n");
+
+ // File descriptor only needed if there are messages to use it.
+ if (!message_generators_.empty()) {
+ std::map<std::string, std::string> vars;
+ vars["root_class_name"] = root_class_name_;
+ vars["package"] = file_->package();
+ vars["objc_prefix"] = FileClassPrefix(file_);
+ switch (file_->syntax()) {
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ vars["syntax"] = "GPBFileSyntaxUnknown";
+ break;
+ case FileDescriptor::SYNTAX_PROTO2:
+ vars["syntax"] = "GPBFileSyntaxProto2";
+ break;
+ case FileDescriptor::SYNTAX_PROTO3:
+ vars["syntax"] = "GPBFileSyntaxProto3";
+ break;
+ }
+ printer->Print(vars,
+ "#pragma mark - $root_class_name$_FileDescriptor\n"
+ "\n"
+ "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety of the singleton.\n"
+ " static GPBFileDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n"
+ " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
+ if (!vars["objc_prefix"].empty()) {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " objcPrefix:@\"$objc_prefix$\"\n"
+ " syntax:$syntax$];\n");
+ } else {
+ printer->Print(
+ vars,
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " syntax:$syntax$];\n");
+ }
+ printer->Print(
+ " }\n"
+ " return descriptor;\n"
+ "}\n"
+ "\n");
+ }
+
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateSource(printer);
+ }
+ for (const auto& generator : message_generators_) {
+ generator->GenerateSource(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "#pragma clang diagnostic pop\n"
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
+}
+
+// Helper to print the import of the runtime support at the top of generated
+// files. This currently only supports the runtime coming from a framework
+// as defined by the official CocoaPod.
+void FileGenerator::PrintFileRuntimePreamble(
+ io::Printer* printer,
+ const std::vector<std::string>& headers_to_import) const {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+ ImportWriter::PrintRuntimeImports(
+ printer, headers_to_import, options_.runtime_import_prefix, true);
+ printer->Print("\n");
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h
new file mode 100644
index 00000000..61572802
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator;
+class ExtensionGenerator;
+class MessageGenerator;
+
+class FileGenerator {
+ public:
+ FileGenerator(const FileDescriptor* file, const Options& options);
+ ~FileGenerator();
+
+ FileGenerator(const FileGenerator&) = delete;
+ FileGenerator& operator=(const FileGenerator&) = delete;
+
+ void GenerateSource(io::Printer* printer);
+ void GenerateHeader(io::Printer* printer);
+
+ private:
+ const FileDescriptor* file_;
+ std::string root_class_name_;
+ bool is_bundled_proto_;
+
+ std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
+ std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
+ std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+
+ const Options options_;
+
+ void PrintFileRuntimePreamble(
+ io::Printer* printer,
+ const std::vector<std::string>& headers_to_import) const;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc
new file mode 100644
index 00000000..3dbd1d43
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -0,0 +1,276 @@
+// 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 <fstream>
+#include <iostream>
+#include <string>
+#include <unordered_set>
+#include <compiler/objectivec/objectivec_generator.h>
+#include <compiler/objectivec/objectivec_file.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+// Convert a string with "yes"/"no" (case insensitive) to a boolean, returning
+// true/false for if the input string was a valid value. If the input string is
+// invalid, `result` is unchanged.
+bool StringToBool(const std::string& value, bool* result) {
+ std::string upper_value(value);
+ UpperString(&upper_value);
+ if (upper_value == "NO") {
+ *result = false;
+ return true;
+ }
+ if (upper_value == "YES") {
+ *result = true;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+ObjectiveCGenerator::ObjectiveCGenerator() {}
+
+ObjectiveCGenerator::~ObjectiveCGenerator() {}
+
+bool ObjectiveCGenerator::HasGenerateAll() const {
+ return true;
+}
+
+bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* context,
+ std::string* error) const {
+ *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+ return false;
+}
+
+bool ObjectiveCGenerator::GenerateAll(
+ const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter, GeneratorContext* context,
+ std::string* error) const {
+ // -----------------------------------------------------------------
+ // Parse generator options. These options are passed to the compiler using the
+ // --objc_opt flag. The options are passed as a comma separated list of
+ // options along with their values. If the option appears multiple times, only
+ // the last value will be considered.
+ //
+ // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
+
+ Options generation_options;
+
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "expected_prefixes_path") {
+ // Path to find a file containing the expected prefixes
+ // (objc_class_prefix "PREFIX") for proto packages (package NAME). The
+ // generator will then issue warnings/errors if in the proto files being
+ // generated the option is not listed/wrong/etc in the file.
+ //
+ // The format of the file is:
+ // - An entry is a line of "package=prefix".
+ // - Comments start with "#".
+ // - A comment can go on a line after a expected package/prefix pair.
+ // (i.e. - "package=prefix # comment")
+ //
+ // There is no validation that the prefixes are good prefixes, it is
+ // assumed that they are when you create the file.
+ generation_options.expected_prefixes_path = options[i].second;
+ } else if (options[i].first == "expected_prefixes_suppressions") {
+ // A semicolon delimited string that lists the paths of .proto files to
+ // exclude from the package prefix validations (expected_prefixes_path).
+ // This is provided as an "out", to skip some files being checked.
+ for (StringPiece split_piece : Split(
+ options[i].second, ";", true)) {
+ generation_options.expected_prefixes_suppressions.push_back(
+ std::string(split_piece));
+ }
+ } else if (options[i].first == "prefixes_must_be_registered") {
+ // If objc prefix file option value must be registered to be used. This
+ // option has no meaning if an "expected_prefixes_path" isn't set. The
+ // available options are:
+ // "no": They don't have to be registered.
+ // "yes": They must be registered and an error will be raised if a files
+ // tried to use a prefix that isn't registered.
+ // Default is "no".
+ if (!StringToBool(options[i].second,
+ &generation_options.prefixes_must_be_registered)) {
+ *error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second;
+ return false;
+ }
+ } else if (options[i].first == "require_prefixes") {
+ // If every file must have an objc prefix file option to be used. The
+ // available options are:
+ // "no": Files can be generated without the prefix option.
+ // "yes": Files must have the objc prefix option, and an error will be
+ // raised if a files doesn't have one.
+ // Default is "no".
+ if (!StringToBool(options[i].second,
+ &generation_options.require_prefixes)) {
+ *error = "error: Unknown value for require_prefixes: " + options[i].second;
+ return false;
+ }
+ } else if (options[i].first == "generate_for_named_framework") {
+ // The name of the framework that protos are being generated for. This
+ // will cause the #import statements to be framework based using this
+ // name (i.e. - "#import <NAME/proto.pbobjc.h>).
+ //
+ // NOTE: If this option is used with
+ // named_framework_to_proto_path_mappings_path, then this is effectively
+ // the "default" framework name used for everything that wasn't mapped by
+ // the mapping file.
+ generation_options.generate_for_named_framework = options[i].second;
+ } else if (options[i].first == "named_framework_to_proto_path_mappings_path") {
+ // Path to find a file containing the list of framework names and proto
+ // files. The generator uses this to decide if a proto file
+ // referenced should use a framework style import vs. a user level import
+ // (#import <FRAMEWORK/file.pbobjc.h> vs #import "dir/file.pbobjc.h").
+ //
+ // The format of the file is:
+ // - An entry is a line of "frameworkName: file.proto, dir/file2.proto".
+ // - Comments start with "#".
+ // - A comment can go on a line after a expected package/prefix pair.
+ // (i.e. - "frameworkName: file.proto # comment")
+ //
+ // Any number of files can be listed for a framework, just separate them
+ // with commas.
+ //
+ // There can be multiple lines listing the same frameworkName in case it
+ // has a lot of proto files included in it; having multiple lines makes
+ // things easier to read. If a proto file is not configured in the
+ // mappings file, it will use the default framework name if one was passed
+ // with generate_for_named_framework, or the relative path to it's include
+ // path otherwise.
+ generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
+ } else if (options[i].first == "runtime_import_prefix") {
+ // Path to use as a prefix on #imports of runtime provided headers in the
+ // generated files. When integrating ObjC protos into a build system,
+ // this can be used to avoid having to add the runtime directory to the
+ // header search path since the generate #import will be more complete.
+ generation_options.runtime_import_prefix =
+ StripSuffixString(options[i].second, "/");
+ } else if (options[i].first == "use_package_as_prefix") {
+ // Controls how the symbols should be prefixed to avoid symbols
+ // collisions. The objc_class_prefix file option is always honored, this
+ // is just what to do if that isn't set. The available options are:
+ // "no": Not prefixed (the existing mode).
+ // "yes": Make a prefix out of the proto package.
+ bool value = false;
+ if (StringToBool(options[i].second, &value)) {
+ SetUseProtoPackageAsDefaultPrefix(value);
+ } else {
+ *error = "error: Unknown use_package_as_prefix: " + options[i].second;
+ return false;
+ }
+ } else if (options[i].first == "proto_package_prefix_exceptions_path") {
+ // Path to find a file containing the list of proto package names that are
+ // exceptions when use_package_as_prefix is enabled. This can be used to
+ // migrate packages one at a time to use_package_as_prefix since there
+ // are likely code updates needed with each one.
+ //
+ // The format of the file is:
+ // - An entry is a line of "proto.package.name".
+ // - Comments start with "#".
+ // - A comment can go on a line after a expected package/prefix pair.
+ // (i.e. - "some.proto.package # comment")
+ SetProtoPackagePrefixExceptionList(options[i].second);
+ } else {
+ *error = "error: Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ // These are not official generation options and could be removed/changed in
+ // the future and doing that won't count as a breaking change.
+ bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != NULL;
+ std::unordered_set<std::string> skip_impls;
+ if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != NULL) {
+ std::ifstream skip_file(getenv("GPB_OBJC_SKIP_IMPLS_FILE"));
+ if (skip_file.is_open()) {
+ std::string line;
+ while (std::getline(skip_file, line)) {
+ skip_impls.insert(line);
+ }
+ } else {
+ *error = "error: Failed to open GPB_OBJC_SKIP_IMPLS_FILE file";
+ return false;
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ // Validate the objc prefix/package pairings.
+ if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
+ // *error will have been filled in.
+ return false;
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ const FileDescriptor* file = files[i];
+ FileGenerator file_generator(file, generation_options);
+ std::string filepath = FilePath(file);
+
+ // Generate header.
+ {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filepath + ".pbobjc.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateHeader(&printer);
+ }
+
+ // Generate m file.
+ if (!headers_only && skip_impls.count(file->name()) == 0) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filepath + ".pbobjc.m"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSource(&printer);
+ }
+ }
+
+ return true;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h
new file mode 100644
index 00000000..c7cfe8d3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h
@@ -0,0 +1,79 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates ObjectiveC code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+
+#include <string>
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// CodeGenerator implementation which generates a ObjectiveC source file and
+// header. If you create your own protocol compiler binary and you want it to
+// support ObjectiveC output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
+ public:
+ ObjectiveCGenerator();
+ ~ObjectiveCGenerator();
+
+ ObjectiveCGenerator(const ObjectiveCGenerator&) = delete;
+ ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete;
+
+ // implements CodeGenerator ----------------------------------------
+ bool HasGenerateAll() const override;
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* context, std::string* error) const override;
+ bool GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter, GeneratorContext* context,
+ std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override {
+ return FEATURE_PROTO3_OPTIONAL;
+ }
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc
new file mode 100644
index 00000000..014edb9e
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -0,0 +1,1960 @@
+// 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 _MSC_VER
+#include <unistd.h>
+#endif
+#include <climits>
+#include <errno.h>
+#include <fcntl.h>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <stdlib.h>
+#include <unordered_set>
+#include <vector>
+
+#include <compiler/code_generator.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <compiler/objectivec/objectivec_nsobject_methods.h>
+#include <descriptor.pb.h>
+#include <io/coded_stream.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream_impl.h>
+#include <io/io_win32.h>
+#include <port.h>
+#include <stubs/common.h>
+#include <stubs/strutil.h>
+
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error cases, so it seems to be ok to use as a back door for errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// <io.h> is transitively included in this file. Import the functions explicitly
+// in this port namespace to avoid ambiguous definition.
+namespace posix {
+#ifdef _WIN32
+using ::google::protobuf::io::win32::open;
+#else
+using ::open;
+#endif
+} // namespace port
+
+namespace {
+
+class SimpleLineCollector : public LineConsumer {
+ public:
+ SimpleLineCollector(std::unordered_set<std::string>* inout_set)
+ : set_(inout_set) {}
+
+ virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override {
+ set_->insert(std::string(line));
+ return true;
+ }
+
+ private:
+ std::unordered_set<std::string>* set_;
+};
+
+class PrefixModeStorage {
+ public:
+ PrefixModeStorage();
+
+ bool use_package_name() const { return use_package_name_; }
+ void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; }
+
+ const std::string exception_path() const { return exception_path_; }
+ void set_exception_path(const std::string& path) {
+ exception_path_ = path;
+ exceptions_.clear();
+ }
+
+ bool is_package_exempted(const std::string& package);
+
+ private:
+ bool use_package_name_;
+ std::string exception_path_;
+ std::unordered_set<std::string> exceptions_;
+};
+
+PrefixModeStorage::PrefixModeStorage() {
+ // Even thought there are generation options, have an env back door since some
+ // of these helpers could be used in other plugins.
+
+ const char* use_package_cstr = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX");
+ use_package_name_ =
+ (use_package_cstr && (std::string("YES") == ToUpper(use_package_cstr)));
+
+ const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
+ if (exception_path) {
+ exception_path_ = exception_path;
+ }
+}
+
+bool PrefixModeStorage::is_package_exempted(const std::string& package) {
+ if (exceptions_.empty() && !exception_path_.empty()) {
+ std::string error_str;
+ SimpleLineCollector collector(&exceptions_);
+ if (!ParseSimpleFile(exception_path_, &collector, &error_str)) {
+ if (error_str.empty()) {
+ error_str = std::string("protoc:0: warning: Failed to parse")
+ + std::string(" package prefix exceptions file: ")
+ + exception_path_;
+ }
+ std::cerr << error_str << std::endl;
+ std::cerr.flush();
+ exceptions_.clear();
+ }
+
+ // If the file was empty put something in it so it doesn't get reloaded over
+ // and over.
+ if (exceptions_.empty()) {
+ exceptions_.insert("<not a real package>");
+ }
+ }
+
+ return exceptions_.count(package) != 0;
+}
+
+PrefixModeStorage g_prefix_mode;
+
+} // namespace
+
+bool UseProtoPackageAsDefaultPrefix() {
+ return g_prefix_mode.use_package_name();
+}
+
+void SetUseProtoPackageAsDefaultPrefix(bool on_or_off) {
+ g_prefix_mode.set_use_package_name(on_or_off);
+}
+
+std::string GetProtoPackagePrefixExceptionList() {
+ return g_prefix_mode.exception_path();
+}
+
+void SetProtoPackagePrefixExceptionList(const std::string& file_path) {
+ g_prefix_mode.set_exception_path(file_path);
+}
+
+Options::Options() {
+ // Default is the value of the env for the package prefixes.
+ const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+ if (file_path) {
+ expected_prefixes_path = file_path;
+ }
+ const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
+ if (suppressions) {
+ expected_prefixes_suppressions =
+ Split(suppressions, ";", true);
+ }
+ prefixes_must_be_registered = false;
+ require_prefixes = false;
+}
+
+namespace {
+
+std::unordered_set<std::string> MakeWordsMap(const char* const words[],
+ size_t num_words) {
+ std::unordered_set<std::string> result;
+ for (int i = 0; i < num_words; i++) {
+ result.insert(words[i]);
+ }
+ return result;
+}
+
+const char* const kUpperSegmentsList[] = {"url", "http", "https"};
+
+std::unordered_set<std::string> kUpperSegments =
+ MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
+
+bool ascii_isnewline(char c) {
+ return c == '\n' || c == '\r';
+}
+
+// Internal helper for name handing.
+// Do not expose this outside of helpers, stick to having functions for specific
+// cases (ClassName(), FieldName()), so there is always consistent suffix rules.
+std::string UnderscoresToCamelCase(const std::string& input,
+ bool first_capitalized) {
+ std::vector<std::string> values;
+ std::string current;
+
+ bool last_char_was_number = false;
+ bool last_char_was_lower = false;
+ bool last_char_was_upper = false;
+ for (int i = 0; i < input.size(); i++) {
+ char c = input[i];
+ if (ascii_isdigit(c)) {
+ if (!last_char_was_number) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c;
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_number = true;
+ } else if (ascii_islower(c)) {
+ // lowercase letter can follow a lowercase or uppercase letter
+ if (!last_char_was_lower && !last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c; // already lower
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_lower = true;
+ } else if (ascii_isupper(c)) {
+ if (!last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += ascii_tolower(c);
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_upper = true;
+ } else {
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ }
+ }
+ values.push_back(current);
+
+ std::string result;
+ bool first_segment_forces_upper = false;
+ for (std::vector<std::string>::iterator i = values.begin(); i != values.end();
+ ++i) {
+ std::string value = *i;
+ bool all_upper = (kUpperSegments.count(value) > 0);
+ if (all_upper && (result.length() == 0)) {
+ first_segment_forces_upper = true;
+ }
+ for (int j = 0; j < value.length(); j++) {
+ if (j == 0 || all_upper) {
+ value[j] = ascii_toupper(value[j]);
+ } else {
+ // Nothing, already in lower.
+ }
+ }
+ result += value;
+ }
+ if ((result.length() != 0) &&
+ !first_capitalized &&
+ !first_segment_forces_upper) {
+ result[0] = ascii_tolower(result[0]);
+ }
+ return result;
+}
+
+const char* const kReservedWordList[] = {
+ // Note NSObject Methods:
+ // These are brought in from objectivec_nsobject_methods.h that is generated
+ // using method_dump.sh. See kNSObjectMethods below.
+
+ // Objective C "keywords" that aren't in C
+ // From
+ // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+ // with some others added on.
+ "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
+ "self", "instancetype", "nullable", "nonnull", "nil", "Nil",
+ "YES", "NO", "weak",
+
+ // C/C++ keywords (Incl C++ 0x11)
+ // From http://en.cppreference.com/w/cpp/keywords
+ "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
+ "compl", "const", "constexpr", "const_cast", "continue", "decltype",
+ "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
+ "export", "extern ", "false", "float", "for", "friend", "goto", "if",
+ "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
+ "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
+ "public", "register", "reinterpret_cast", "return", "short", "signed",
+ "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
+ "template", "this", "thread_local", "throw", "true", "try", "typedef",
+ "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+ "volatile", "wchar_t", "while", "xor", "xor_eq",
+
+ // C99 keywords
+ // From
+ // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+ "restrict",
+
+ // GCC/Clang extension
+ "typeof",
+
+ // Not a keyword, but will break you
+ "NULL",
+
+ // C88+ specs call for these to be macros, so depending on what they are
+ // defined to be it can lead to odd errors for some Xcode/SDK versions.
+ "stdin", "stdout", "stderr",
+
+ // Objective-C Runtime typedefs
+ // From <obc/runtime.h>
+ "Category", "Ivar", "Method", "Protocol",
+
+ // GPBMessage Methods
+ // Only need to add instance methods that may conflict with
+ // method declared in protos. The main cases are methods
+ // that take no arguments, or setFoo:/hasFoo: type methods.
+ "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
+ "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
+ "sortedExtensionsInUse", "unknownFields",
+
+ // MacTypes.h names
+ "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
+ "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
+ "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
+ "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
+ "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
+};
+
+// returns true is input starts with __ or _[A-Z] which are reserved identifiers
+// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here
+// but this verifies and allows for future expansion if we decide to redefine what a
+// reserved C identifier is (for example the GNU list
+// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html )
+bool IsReservedCIdentifier(const std::string& input) {
+ if (input.length() > 2) {
+ if (input.at(0) == '_') {
+ if (isupper(input.at(1)) || input.at(1) == '_') {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+std::string SanitizeNameForObjC(const std::string& prefix,
+ const std::string& input,
+ const std::string& extension,
+ std::string* out_suffix_added) {
+ static const std::unordered_set<std::string> kReservedWords =
+ MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+ static const std::unordered_set<std::string> kNSObjectMethods =
+ MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
+ std::string sanitized;
+ // We add the prefix in the cases where the string is missing a prefix.
+ // We define "missing a prefix" as where 'input':
+ // a) Doesn't start with the prefix or
+ // b) Isn't equivalent to the prefix or
+ // c) Has the prefix, but the letter after the prefix is lowercase
+ if (HasPrefixString(input, prefix)) {
+ if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) {
+ sanitized = prefix + input;
+ } else {
+ sanitized = input;
+ }
+ } else {
+ sanitized = prefix + input;
+ }
+ if (IsReservedCIdentifier(sanitized) ||
+ (kReservedWords.count(sanitized) > 0) ||
+ (kNSObjectMethods.count(sanitized) > 0)) {
+ if (out_suffix_added) *out_suffix_added = extension;
+ return sanitized + extension;
+ }
+ if (out_suffix_added) out_suffix_added->clear();
+ return sanitized;
+}
+
+std::string NameFromFieldDescriptor(const FieldDescriptor* field) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ return field->message_type()->name();
+ } else {
+ return field->name();
+ }
+}
+
+void PathSplit(const std::string& path, std::string* directory,
+ std::string* basename) {
+ std::string::size_type last_slash = path.rfind('/');
+ if (last_slash == std::string::npos) {
+ if (directory) {
+ *directory = "";
+ }
+ if (basename) {
+ *basename = path;
+ }
+ } else {
+ if (directory) {
+ *directory = path.substr(0, last_slash);
+ }
+ if (basename) {
+ *basename = path.substr(last_slash + 1);
+ }
+ }
+}
+
+bool IsSpecialName(const std::string& name, const std::string* special_names,
+ size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ size_t length = special_names[i].length();
+ if (name.compare(0, length, special_names[i]) == 0) {
+ if (name.length() > length) {
+ // If name is longer than the retained_name[i] that it matches
+ // the next character must be not lower case (newton vs newTon vs
+ // new_ton).
+ return !ascii_islower(name[length]);
+ } else {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlag_None";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionNone";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldNone";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "0";
+ }
+}
+
+std::string GetEnumNameForFlagType(const FlagType flag_type) {
+ switch(flag_type) {
+ case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+ return "GPBDescriptorInitializationFlags";
+ case FLAGTYPE_EXTENSION:
+ return "GPBExtensionOptions";
+ case FLAGTYPE_FIELD:
+ return "GPBFieldFlags";
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return std::string();
+ }
+}
+
+void MaybeUnQuote(StringPiece* input) {
+ if ((input->length() >= 2) &&
+ ((*input->data() == '\'' || *input->data() == '"')) &&
+ ((*input)[input->length() - 1] == *input->data())) {
+ input->remove_prefix(1);
+ input->remove_suffix(1);
+ }
+}
+
+} // namespace
+
+// Escape C++ trigraphs by escaping question marks to \?
+std::string EscapeTrigraphs(const std::string& to_escape) {
+ return StringReplace(to_escape, "?", "\\?", true);
+}
+
+void TrimWhitespace(StringPiece* input) {
+ while (!input->empty() && ascii_isspace(*input->data())) {
+ input->remove_prefix(1);
+ }
+ while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
+ input->remove_suffix(1);
+ }
+}
+
+bool IsRetainedName(const std::string& name) {
+ // List of prefixes from
+ // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
+ static const std::string retained_names[] = {"new", "alloc", "copy",
+ "mutableCopy"};
+ return IsSpecialName(name, retained_names,
+ sizeof(retained_names) / sizeof(retained_names[0]));
+}
+
+bool IsInitName(const std::string& name) {
+ static const std::string init_names[] = {"init"};
+ return IsSpecialName(name, init_names,
+ sizeof(init_names) / sizeof(init_names[0]));
+}
+
+std::string BaseFileName(const FileDescriptor* file) {
+ std::string basename;
+ PathSplit(file->name(), NULL, &basename);
+ return basename;
+}
+
+std::string FileClassPrefix(const FileDescriptor* file) {
+ // Always honor the file option.
+ if (file->options().has_objc_class_prefix()) {
+ return file->options().objc_class_prefix();
+ }
+
+ // If package prefix isn't enabled or no package, done.
+ if (!g_prefix_mode.use_package_name() || file->package().empty()) {
+ return "";
+ }
+
+ // If the package is in the exceptions list, done.
+ if (g_prefix_mode.is_package_exempted(file->package())) {
+ return "";
+ }
+
+ // Transform the package into a prefix: use the dot segments as part,
+ // camelcase each one and then join them with underscores, and add an
+ // underscore at the end.
+ std::string result;
+ const std::vector<std::string> segments = Split(file->package(), ".", true);
+ for (const auto& segment : segments) {
+ const std::string part = UnderscoresToCamelCase(segment, true);
+ if (part.empty()) {
+ continue;
+ }
+ if (!result.empty()) {
+ result.append("_");
+ }
+ result.append(part);
+ }
+ if (!result.empty()) {
+ result.append("_");
+ }
+ return result;
+}
+
+std::string FilePath(const FileDescriptor* file) {
+ std::string output;
+ std::string basename;
+ std::string directory;
+ PathSplit(file->name(), &directory, &basename);
+ if (directory.length() > 0) {
+ output = directory + "/";
+ }
+ basename = StripProto(basename);
+
+ // CamelCase to be more ObjC friendly.
+ basename = UnderscoresToCamelCase(basename, true);
+
+ output += basename;
+ return output;
+}
+
+std::string FilePathBasename(const FileDescriptor* file) {
+ std::string output;
+ std::string basename;
+ std::string directory;
+ PathSplit(file->name(), &directory, &basename);
+ basename = StripProto(basename);
+
+ // CamelCase to be more ObjC friendly.
+ output = UnderscoresToCamelCase(basename, true);
+
+ return output;
+}
+
+std::string FileClassName(const FileDescriptor* file) {
+ const std::string prefix = FileClassPrefix(file);
+ const std::string name =
+ UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root";
+ // There aren't really any reserved words that end in "Root", but playing
+ // it safe and checking.
+ return SanitizeNameForObjC(prefix, name, "_RootClass", NULL);
+}
+
+std::string ClassNameWorker(const Descriptor* descriptor) {
+ std::string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+std::string ClassNameWorker(const EnumDescriptor* descriptor) {
+ std::string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+std::string ClassName(const Descriptor* descriptor) {
+ return ClassName(descriptor, NULL);
+}
+
+std::string ClassName(const Descriptor* descriptor,
+ std::string* out_suffix_added) {
+ // 1. Message names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the very end and then suffix things.
+ const std::string prefix = FileClassPrefix(descriptor->file());
+ const std::string name = ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added);
+}
+
+std::string EnumName(const EnumDescriptor* descriptor) {
+ // 1. Enum names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the every end and then suffix things.
+ // message Fixed {
+ // message Size {...}
+ // enum Mumble {...}
+ // ...
+ // }
+ // yields Fixed_Class, Fixed_Size.
+ const std::string prefix = FileClassPrefix(descriptor->file());
+ const std::string name = ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(prefix, name, "_Enum", NULL);
+}
+
+std::string EnumValueName(const EnumValueDescriptor* descriptor) {
+ // Because of the Switch enum compatibility, the name on the enum has to have
+ // the suffix handing, so it slightly diverges from how nested classes work.
+ // enum Fixed {
+ // FOO = 1
+ // }
+ // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
+ const std::string class_name = EnumName(descriptor->type());
+ const std::string value_str =
+ UnderscoresToCamelCase(descriptor->name(), true);
+ const std::string name = class_name + "_" + value_str;
+ // There aren't really any reserved words with an underscore and a leading
+ // capital letter, but playing it safe and checking.
+ return SanitizeNameForObjC("", name, "_Value", NULL);
+}
+
+std::string EnumValueShortName(const EnumValueDescriptor* descriptor) {
+ // Enum value names (EnumValueName above) are the enum name turned into
+ // a class name and then the value name is CamelCased and concatenated; the
+ // whole thing then gets sanitized for reserved words.
+ // The "short name" is intended to be the final leaf, the value name; but
+ // you can't simply send that off to sanitize as that could result in it
+ // getting modified when the full name didn't. For example enum
+ // "StorageModes" has a value "retain". So the full name is
+ // "StorageModes_Retain", but if we sanitize "retain" it would become
+ // "RetainValue".
+ // So the right way to get the short name is to take the full enum name
+ // and then strip off the enum name (leaving the value name and anything
+ // done by sanitize).
+ const std::string class_name = EnumName(descriptor->type());
+ const std::string long_name_prefix = class_name + "_";
+ const std::string long_name = EnumValueName(descriptor);
+ return StripPrefixString(long_name, long_name_prefix);
+}
+
+std::string UnCamelCaseEnumShortName(const std::string& name) {
+ std::string result;
+ for (int i = 0; i < name.size(); i++) {
+ char c = name[i];
+ if (i > 0 && ascii_isupper(c)) {
+ result += '_';
+ }
+ result += ascii_toupper(c);
+ }
+ return result;
+}
+
+std::string ExtensionMethodName(const FieldDescriptor* descriptor) {
+ const std::string name = NameFromFieldDescriptor(descriptor);
+ const std::string result = UnderscoresToCamelCase(name, false);
+ return SanitizeNameForObjC("", result, "_Extension", NULL);
+}
+
+std::string FieldName(const FieldDescriptor* field) {
+ const std::string name = NameFromFieldDescriptor(field);
+ std::string result = UnderscoresToCamelCase(name, false);
+ if (field->is_repeated() && !field->is_map()) {
+ // Add "Array" before do check for reserved worlds.
+ result += "Array";
+ } else {
+ // If it wasn't repeated, but ends in "Array", force on the _p suffix.
+ if (HasSuffixString(result, "Array")) {
+ result += "_p";
+ }
+ }
+ return SanitizeNameForObjC("", result, "_p", NULL);
+}
+
+std::string FieldNameCapitalized(const FieldDescriptor* field) {
+ // Want the same suffix handling, so upcase the first letter of the other
+ // name.
+ std::string result = FieldName(field);
+ if (result.length() > 0) {
+ result[0] = ascii_toupper(result[0]);
+ }
+ return result;
+}
+
+std::string OneofEnumName(const OneofDescriptor* descriptor) {
+ const Descriptor* fieldDescriptor = descriptor->containing_type();
+ std::string name = ClassName(fieldDescriptor);
+ name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
+ // No sanitize needed because the OS never has names that end in _OneOfCase.
+ return name;
+}
+
+std::string OneofName(const OneofDescriptor* descriptor) {
+ std::string name = UnderscoresToCamelCase(descriptor->name(), false);
+ // No sanitize needed because it gets OneOfCase added and that shouldn't
+ // ever conflict.
+ return name;
+}
+
+std::string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+ // Use the common handling and then up-case the first letter.
+ std::string result = OneofName(descriptor);
+ if (result.length() > 0) {
+ result[0] = ascii_toupper(result[0]);
+ }
+ return result;
+}
+
+std::string ObjCClass(const std::string& class_name) {
+ return std::string("GPBObjCClass(") + class_name + ")";
+}
+
+std::string ObjCClassDeclaration(const std::string& class_name) {
+ return std::string("GPBObjCClassDeclaration(") + class_name + ");";
+}
+
+std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) {
+ std::string worker(name);
+ if (HasSuffixString(worker, "_p")) {
+ worker = StripSuffixString(worker, "_p");
+ }
+ if (field->is_repeated() && HasSuffixString(worker, "Array")) {
+ worker = StripSuffixString(worker, "Array");
+ }
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (worker.length() > 0) {
+ if (ascii_islower(worker[0])) {
+ worker[0] = ascii_toupper(worker[0]);
+ }
+ }
+ return worker;
+ } else {
+ std::string result;
+ for (int i = 0; i < worker.size(); i++) {
+ char c = worker[i];
+ if (ascii_isupper(c)) {
+ if (i > 0) {
+ result += '_';
+ }
+ result += ascii_tolower(c);
+ } else {
+ result += c;
+ }
+ }
+ return result;
+ }
+}
+
+std::string GetCapitalizedType(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ return "Int32";
+ case FieldDescriptor::TYPE_UINT32:
+ return "UInt32";
+ case FieldDescriptor::TYPE_SINT32:
+ return "SInt32";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "Fixed32";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "SFixed32";
+ case FieldDescriptor::TYPE_INT64:
+ return "Int64";
+ case FieldDescriptor::TYPE_UINT64:
+ return "UInt64";
+ case FieldDescriptor::TYPE_SINT64:
+ return "SInt64";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "Fixed64";
+ case FieldDescriptor::TYPE_SFIXED64:
+ return "SFixed64";
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_DOUBLE:
+ return "Double";
+ case FieldDescriptor::TYPE_BOOL:
+ return "Bool";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ case FieldDescriptor::TYPE_GROUP:
+ return "Group";
+ case FieldDescriptor::TYPE_MESSAGE:
+ return "Message";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return std::string();
+}
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
+ switch (field_type) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ return OBJECTIVECTYPE_INT32;
+
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ return OBJECTIVECTYPE_UINT32;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ return OBJECTIVECTYPE_INT64;
+
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return OBJECTIVECTYPE_UINT64;
+
+ case FieldDescriptor::TYPE_FLOAT:
+ return OBJECTIVECTYPE_FLOAT;
+
+ case FieldDescriptor::TYPE_DOUBLE:
+ return OBJECTIVECTYPE_DOUBLE;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return OBJECTIVECTYPE_BOOLEAN;
+
+ case FieldDescriptor::TYPE_STRING:
+ return OBJECTIVECTYPE_STRING;
+
+ case FieldDescriptor::TYPE_BYTES:
+ return OBJECTIVECTYPE_DATA;
+
+ case FieldDescriptor::TYPE_ENUM:
+ return OBJECTIVECTYPE_ENUM;
+
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ return OBJECTIVECTYPE_MESSAGE;
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return OBJECTIVECTYPE_INT32;
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field) {
+ ObjectiveCType type = GetObjectiveCType(field);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ case OBJECTIVECTYPE_UINT32:
+ case OBJECTIVECTYPE_INT64:
+ case OBJECTIVECTYPE_UINT64:
+ case OBJECTIVECTYPE_FLOAT:
+ case OBJECTIVECTYPE_DOUBLE:
+ case OBJECTIVECTYPE_BOOLEAN:
+ case OBJECTIVECTYPE_ENUM:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool IsReferenceType(const FieldDescriptor* field) {
+ return !IsPrimitiveType(field);
+}
+
+static std::string HandleExtremeFloatingPoint(std::string val,
+ bool add_float_suffix) {
+ if (val == "nan") {
+ return "NAN";
+ } else if (val == "inf") {
+ return "INFINITY";
+ } else if (val == "-inf") {
+ return "-INFINITY";
+ } else {
+ // float strings with ., e or E need to have f appended
+ if (add_float_suffix && (val.find(".") != std::string::npos ||
+ val.find("e") != std::string::npos ||
+ val.find("E") != std::string::npos)) {
+ val += "f";
+ }
+ return val;
+ }
+}
+
+std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
+ // Returns the field within the GPBGenericValue union to use for the given
+ // field.
+ if (field->is_repeated()) {
+ return "valueMessage";
+ }
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return "valueInt32";
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return "valueUInt32";
+ case FieldDescriptor::CPPTYPE_INT64:
+ return "valueInt64";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return "valueUInt64";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "valueFloat";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "valueDouble";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "valueBool";
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ return "valueData";
+ } else {
+ return "valueString";
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return "valueEnum";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "valueMessage";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return std::string();
+}
+
+
+std::string DefaultValue(const FieldDescriptor* field) {
+ // Repeated fields don't have defaults.
+ if (field->is_repeated()) {
+ return "nil";
+ }
+
+ // Switch on cpp_type since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int32() == INT_MIN) {
+ return "-0x80000000";
+ }
+ return StrCat(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return StrCat(field->default_value_uint32()) + "U";
+ case FieldDescriptor::CPPTYPE_INT64:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int64() == LLONG_MIN) {
+ return "-0x8000000000000000LL";
+ }
+ return StrCat(field->default_value_int64()) + "LL";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return StrCat(field->default_value_uint64()) + "ULL";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return HandleExtremeFloatingPoint(
+ SimpleDtoa(field->default_value_double()), false);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return HandleExtremeFloatingPoint(
+ SimpleFtoa(field->default_value_float()), true);
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "YES" : "NO";
+ case FieldDescriptor::CPPTYPE_STRING: {
+ const bool has_default_value = field->has_default_value();
+ const std::string& default_string = field->default_value_string();
+ if (!has_default_value || default_string.length() == 0) {
+ // If the field is defined as being the empty string,
+ // then we will just assign to nil, as the empty string is the
+ // default for both strings and data.
+ return "nil";
+ }
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ // We want constant fields in our data structures so we can
+ // declare them as static. To achieve this we cheat and stuff
+ // a escaped c string (prefixed with a length) into the data
+ // field, and cast it to an (NSData*) so it will compile.
+ // The runtime library knows how to handle it.
+
+ // Must convert to a standard byte order for packing length into
+ // a cstring.
+ uint32_t length = ghtonl(default_string.length());
+ std::string bytes((const char*)&length, sizeof(length));
+ bytes.append(default_string);
+ return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
+ } else {
+ return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return EnumValueName(field->default_value_enum());
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "nil";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return std::string();
+}
+
+bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
+ // Repeated fields don't have defaults.
+ if (field->is_repeated()) {
+ return false;
+ }
+
+ // As much as checking field->has_default_value() seems useful, it isn't
+ // because of enums. proto2 syntax allows the first item in an enum (the
+ // default) to be non zero. So checking field->has_default_value() would
+ // result in missing this non zero default. See MessageWithOneBasedEnum in
+ // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
+
+ // Some proto file set the default to the zero value, so make sure the value
+ // isn't the zero case.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return field->default_value_int32() != 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return field->default_value_uint32() != 0U;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return field->default_value_int64() != 0LL;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return field->default_value_uint64() != 0ULL;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return field->default_value_double() != 0.0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return field->default_value_float() != 0.0f;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool();
+ case FieldDescriptor::CPPTYPE_STRING: {
+ const std::string& default_string = field->default_value_string();
+ return default_string.length() != 0;
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return field->default_value_enum()->number() != 0;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return false;
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+}
+
+std::string BuildFlagsString(const FlagType flag_type,
+ const std::vector<std::string>& strings) {
+ if (strings.empty()) {
+ return GetZeroEnumNameForFlagType(flag_type);
+ } else if (strings.size() == 1) {
+ return strings[0];
+ }
+ std::string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
+ for (size_t i = 0; i != strings.size(); ++i) {
+ if (i > 0) {
+ string.append(" | ");
+ }
+ string.append(strings[i]);
+ }
+ string.append(")");
+ return string;
+}
+
+std::string BuildCommentsString(const SourceLocation& location,
+ bool prefer_single_line) {
+ const std::string& comments = location.leading_comments.empty()
+ ? location.trailing_comments
+ : location.leading_comments;
+ std::vector<std::string> lines;
+ lines = Split(comments, "\n", false);
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ // If there are no comments, just return an empty string.
+ if (lines.empty()) {
+ return "";
+ }
+
+ std::string prefix;
+ std::string suffix;
+ std::string final_comments;
+ std::string epilogue;
+
+ bool add_leading_space = false;
+
+ if (prefer_single_line && lines.size() == 1) {
+ prefix = "/** ";
+ suffix = " */\n";
+ } else {
+ prefix = "* ";
+ suffix = "\n";
+ final_comments += "/**\n";
+ epilogue = " **/\n";
+ add_leading_space = true;
+ }
+
+ for (int i = 0; i < lines.size(); i++) {
+ std::string line = StripPrefixString(lines[i], " ");
+ // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
+ line = StringReplace(line, "\\", "\\\\", true);
+ line = StringReplace(line, "@", "\\@", true);
+ // Decouple / from * to not have inline comments inside comments.
+ line = StringReplace(line, "/*", "/\\*", true);
+ line = StringReplace(line, "*/", "*\\/", true);
+ line = prefix + line;
+ StripWhitespace(&line);
+ // If not a one line, need to add the first space before *, as
+ // StripWhitespace would have removed it.
+ line = (add_leading_space ? " " : "") + line;
+ final_comments += line + suffix;
+ }
+ final_comments += epilogue;
+ return final_comments;
+}
+
+// Making these a generator option for folks that don't use CocoaPods, but do
+// want to put the library in a framework is an interesting question. The
+// problem is it means changing sources shipped with the library to actually
+// use a different value; so it isn't as simple as a option.
+const char* const ProtobufLibraryFrameworkName = "Protobuf";
+
+std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) {
+ // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
+ std::string result = std::string("GPB_USE_");
+ result += ToUpper(framework_name);
+ result += "_FRAMEWORK_IMPORTS";
+ return result;
+}
+
+bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
+ // We don't check the name prefix or proto package because some files
+ // (descriptor.proto), aren't shipped generated by the library, so this
+ // seems to be the safest way to only catch the ones shipped.
+ const std::string name = file->name();
+ if (name == "google/protobuf/any.proto" ||
+ name == "google/protobuf/api.proto" ||
+ name == "google/protobuf/duration.proto" ||
+ name == "google/protobuf/empty.proto" ||
+ name == "google/protobuf/field_mask.proto" ||
+ name == "google/protobuf/source_context.proto" ||
+ name == "google/protobuf/struct.proto" ||
+ name == "google/protobuf/timestamp.proto" ||
+ name == "google/protobuf/type.proto" ||
+ name == "google/protobuf/wrappers.proto") {
+ return true;
+ }
+ return false;
+}
+
+bool ReadLine(StringPiece* input, StringPiece* line) {
+ for (int len = 0; len < input->size(); ++len) {
+ if (ascii_isnewline((*input)[len])) {
+ *line = StringPiece(input->data(), len);
+ ++len; // advance over the newline
+ *input = StringPiece(input->data() + len, input->size() - len);
+ return true;
+ }
+ }
+ return false; // Ran out of input with no newline.
+}
+
+void RemoveComment(StringPiece* input) {
+ int offset = input->find('#');
+ if (offset != StringPiece::npos) {
+ input->remove_suffix(input->length() - offset);
+ }
+}
+
+namespace {
+
+class ExpectedPrefixesCollector : public LineConsumer {
+ public:
+ ExpectedPrefixesCollector(std::map<std::string, std::string>* inout_package_to_prefix_map)
+ : prefix_map_(inout_package_to_prefix_map) {}
+
+ virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
+
+ private:
+ std::map<std::string, std::string>* prefix_map_;
+};
+
+bool ExpectedPrefixesCollector::ConsumeLine(
+ const StringPiece& line, std::string* out_error) {
+ int offset = line.find('=');
+ if (offset == StringPiece::npos) {
+ *out_error = std::string("Expected prefixes file line without equal sign: '") +
+ std::string(line) + "'.";
+ return false;
+ }
+ StringPiece package = line.substr(0, offset);
+ StringPiece prefix = line.substr(offset + 1);
+ TrimWhitespace(&package);
+ TrimWhitespace(&prefix);
+ MaybeUnQuote(&prefix);
+ // Don't really worry about error checking the package/prefix for
+ // being valid. Assume the file is validated when it is created/edited.
+ (*prefix_map_)[std::string(package)] = std::string(prefix);
+ return true;
+}
+
+bool LoadExpectedPackagePrefixes(const Options& generation_options,
+ std::map<std::string, std::string>* prefix_map,
+ std::string* out_error) {
+ if (generation_options.expected_prefixes_path.empty()) {
+ return true;
+ }
+
+ ExpectedPrefixesCollector collector(prefix_map);
+ return ParseSimpleFile(
+ generation_options.expected_prefixes_path, &collector, out_error);
+}
+
+bool ValidateObjCClassPrefix(
+ const FileDescriptor* file, const std::string& expected_prefixes_path,
+ const std::map<std::string, std::string>& expected_package_prefixes,
+ bool prefixes_must_be_registered, bool require_prefixes,
+ std::string* out_error) {
+ // Reminder: An explicit prefix option of "" is valid in case the default
+ // prefixing is set to use the proto package and a file needs to be generated
+ // without any prefix at all (for legacy reasons).
+
+ bool has_prefix = file->options().has_objc_class_prefix();
+ bool have_expected_prefix_file = !expected_prefixes_path.empty();
+
+ const std::string prefix = file->options().objc_class_prefix();
+ const std::string package = file->package();
+
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error cases, so it seems to be ok to use as a back door for warnings.
+
+ // Check: Error - See if there was an expected prefix for the package and
+ // report if it doesn't match (wrong or missing).
+ std::map<std::string, std::string>::const_iterator package_match =
+ expected_package_prefixes.find(package);
+ if (package_match != expected_package_prefixes.end()) {
+ // There was an entry, and...
+ if (has_prefix && package_match->second == prefix) {
+ // ...it matches. All good, out of here!
+ return true;
+ } else {
+ // ...it didn't match!
+ *out_error = "error: Expected 'option objc_class_prefix = \"" +
+ package_match->second + "\";' for package '" + package +
+ "' in '" + file->name() + "'";
+ if (has_prefix) {
+ *out_error += "; but found '" + prefix + "' instead";
+ }
+ *out_error += ".";
+ return false;
+ }
+ }
+
+ // If there was no prefix option, we're done at this point.
+ if (!has_prefix) {
+ if (require_prefixes) {
+ *out_error =
+ "error: '" + file->name() + "' does not have a required 'option" +
+ " objc_class_prefix'.";
+ return false;
+ }
+ return true;
+ }
+
+ // When the prefix is non empty, check it against the expected entries.
+ if (!prefix.empty() && have_expected_prefix_file) {
+ // For a non empty prefix, look for any other package that uses the prefix.
+ std::string other_package_for_prefix;
+ for (std::map<std::string, std::string>::const_iterator i =
+ expected_package_prefixes.begin();
+ i != expected_package_prefixes.end(); ++i) {
+ if (i->second == prefix) {
+ other_package_for_prefix = i->first;
+ break;
+ }
+ }
+
+ // Check: Warning - If the file does not have a package, check whether the
+ // prefix was declared is being used by another package or not. This is
+ // a special case for empty packages.
+ if (package.empty()) {
+ // The file does not have a package and ...
+ if (other_package_for_prefix.empty()) {
+ // ... no other package has declared that prefix.
+ std::cerr
+ << "protoc:0: warning: File '" << file->name() << "' has no "
+ << "package. Consider adding a new package to the proto and adding '"
+ << "new.package = " << prefix << "' to the expected prefixes file ("
+ << expected_prefixes_path << ")." << std::endl;
+ std::cerr.flush();
+ } else {
+ // ... another package has declared the same prefix.
+ std::cerr
+ << "protoc:0: warning: File '" << file->name() << "' has no package "
+ << "and package '" << other_package_for_prefix << "' already uses '"
+ << prefix << "' as its prefix. Consider either adding a new package "
+ << "to the proto, or reusing one of the packages already using this "
+ << "prefix in the expected prefixes file ("
+ << expected_prefixes_path << ")." << std::endl;
+ std::cerr.flush();
+ }
+ return true;
+ }
+
+ // Check: Error - Make sure the prefix wasn't expected for a different
+ // package (overlap is allowed, but it has to be listed as an expected
+ // overlap).
+ if (!other_package_for_prefix.empty()) {
+ *out_error =
+ "error: Found 'option objc_class_prefix = \"" + prefix +
+ "\";' in '" + file->name() +
+ "'; that prefix is already used for 'package " +
+ other_package_for_prefix + ";'. It can only be reused by listing " +
+ "it in the expected file (" +
+ expected_prefixes_path + ").";
+ return false; // Only report first usage of the prefix.
+ }
+ } // !prefix.empty()
+
+ // Check: Warning - Make sure the prefix is is a reasonable value according
+ // to Apple's rules (the checks above implicitly whitelist anything that
+ // doesn't meet these rules).
+ if (!prefix.empty() && !ascii_isupper(prefix[0])) {
+ std::cerr
+ << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+ << prefix << "\";' in '" << file->name() << "';"
+ << " it should start with a capital letter." << std::endl;
+ std::cerr.flush();
+ }
+ if (!prefix.empty() && prefix.length() < 3) {
+ // Apple reserves 2 character prefixes for themselves. They do use some
+ // 3 character prefixes, but they haven't updated the rules/docs.
+ std::cerr
+ << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+ << prefix << "\";' in '" << file->name() << "';"
+ << " Apple recommends they should be at least 3 characters long."
+ << std::endl;
+ std::cerr.flush();
+ }
+
+ // Check: Error/Warning - If the given package/prefix pair wasn't expected,
+ // issue a error/warning to added to the file.
+ if (have_expected_prefix_file) {
+ if (prefixes_must_be_registered) {
+ *out_error =
+ "error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
+ prefix + "\";', but it is not registered; add it to the expected " +
+ "prefixes file (" + expected_prefixes_path + ") for the package '" +
+ package + "'.";
+ return false;
+ }
+
+ std::cerr
+ << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
+ << prefix << "\";' in '" << file->name() << "';"
+ << " consider adding it to the expected prefixes file ("
+ << expected_prefixes_path << ")." << std::endl;
+ std::cerr.flush();
+ }
+
+ return true;
+}
+
+} // namespace
+
+bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
+ const Options& generation_options,
+ std::string* out_error) {
+ // Allow a '-' as the path for the expected prefixes to completely disable
+ // even the most basic of checks.
+ if (generation_options.expected_prefixes_path == "-") {
+ return true;
+ }
+
+ // Load the expected package prefixes, if available, to validate against.
+ std::map<std::string, std::string> expected_package_prefixes;
+ if (!LoadExpectedPackagePrefixes(generation_options,
+ &expected_package_prefixes,
+ out_error)) {
+ return false;
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ bool should_skip =
+ (std::find(generation_options.expected_prefixes_suppressions.begin(),
+ generation_options.expected_prefixes_suppressions.end(),
+ files[i]->name())
+ != generation_options.expected_prefixes_suppressions.end());
+ if (should_skip) {
+ continue;
+ }
+
+ bool is_valid =
+ ValidateObjCClassPrefix(files[i],
+ generation_options.expected_prefixes_path,
+ expected_package_prefixes,
+ generation_options.prefixes_must_be_registered,
+ generation_options.require_prefixes,
+ out_error);
+ if (!is_valid) {
+ return false;
+ }
+ }
+ return true;
+}
+
+TextFormatDecodeData::TextFormatDecodeData() { }
+
+TextFormatDecodeData::~TextFormatDecodeData() { }
+
+void TextFormatDecodeData::AddString(int32_t key,
+ const std::string& input_for_decode,
+ const std::string& desired_output) {
+ for (std::vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ if (i->first == key) {
+ std::cerr << "error: duplicate key (" << key
+ << ") making TextFormat data, input: \"" << input_for_decode
+ << "\", desired: \"" << desired_output << "\"." << std::endl;
+ std::cerr.flush();
+ abort();
+ }
+ }
+
+ const std::string& data = TextFormatDecodeData::DecodeDataForString(
+ input_for_decode, desired_output);
+ entries_.push_back(DataEntry(key, data));
+}
+
+std::string TextFormatDecodeData::Data() const {
+ std::ostringstream data_stringstream;
+
+ if (num_entries() > 0) {
+ io::OstreamOutputStream data_outputstream(&data_stringstream);
+ io::CodedOutputStream output_stream(&data_outputstream);
+
+ output_stream.WriteVarint32(num_entries());
+ for (std::vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ output_stream.WriteVarint32(i->first);
+ output_stream.WriteString(i->second);
+ }
+ }
+
+ data_stringstream.flush();
+ return data_stringstream.str();
+}
+
+namespace {
+
+// Helper to build up the decode data for a string.
+class DecodeDataBuilder {
+ public:
+ DecodeDataBuilder() { Reset(); }
+
+ bool AddCharacter(const char desired, const char input);
+ void AddUnderscore() {
+ Push();
+ need_underscore_ = true;
+ }
+ std::string Finish() {
+ Push();
+ return decode_data_;
+ }
+
+ private:
+ static constexpr uint8_t kAddUnderscore = 0x80;
+
+ static constexpr uint8_t kOpAsIs = 0x00;
+ static constexpr uint8_t kOpFirstUpper = 0x40;
+ static constexpr uint8_t kOpFirstLower = 0x20;
+ static constexpr uint8_t kOpAllUpper = 0x60;
+
+ static constexpr int kMaxSegmentLen = 0x1f;
+
+ void AddChar(const char desired) {
+ ++segment_len_;
+ is_all_upper_ &= ascii_isupper(desired);
+ }
+
+ void Push() {
+ uint8_t op = (op_ | segment_len_);
+ if (need_underscore_) op |= kAddUnderscore;
+ if (op != 0) {
+ decode_data_ += (char)op;
+ }
+ Reset();
+ }
+
+ bool AddFirst(const char desired, const char input) {
+ if (desired == input) {
+ op_ = kOpAsIs;
+ } else if (desired == ascii_toupper(input)) {
+ op_ = kOpFirstUpper;
+ } else if (desired == ascii_tolower(input)) {
+ op_ = kOpFirstLower;
+ } else {
+ // Can't be transformed to match.
+ return false;
+ }
+ AddChar(desired);
+ return true;
+ }
+
+ void Reset() {
+ need_underscore_ = false;
+ op_ = 0;
+ segment_len_ = 0;
+ is_all_upper_ = true;
+ }
+
+ bool need_underscore_;
+ bool is_all_upper_;
+ uint8_t op_;
+ int segment_len_;
+
+ std::string decode_data_;
+};
+
+bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
+ // If we've hit the max size, push to start a new segment.
+ if (segment_len_ == kMaxSegmentLen) {
+ Push();
+ }
+ if (segment_len_ == 0) {
+ return AddFirst(desired, input);
+ }
+
+ // Desired and input match...
+ if (desired == input) {
+ // If we aren't transforming it, or we're upper casing it and it is
+ // supposed to be uppercase; just add it to the segment.
+ if ((op_ != kOpAllUpper) || ascii_isupper(desired)) {
+ AddChar(desired);
+ return true;
+ }
+
+ // Add the current segment, and start the next one.
+ Push();
+ return AddFirst(desired, input);
+ }
+
+ // If we need to uppercase, and everything so far has been uppercase,
+ // promote op to AllUpper.
+ if ((desired == ascii_toupper(input)) && is_all_upper_) {
+ op_ = kOpAllUpper;
+ AddChar(desired);
+ return true;
+ }
+
+ // Give up, push and start a new segment.
+ Push();
+ return AddFirst(desired, input);
+}
+
+// If decode data can't be generated, a directive for the raw string
+// is used instead.
+std::string DirectDecodeString(const std::string& str) {
+ std::string result;
+ result += (char)'\0'; // Marker for full string.
+ result += str;
+ result += (char)'\0'; // End of string.
+ return result;
+}
+
+} // namespace
+
+// static
+std::string TextFormatDecodeData::DecodeDataForString(
+ const std::string& input_for_decode, const std::string& desired_output) {
+ if (input_for_decode.empty() || desired_output.empty()) {
+ std::cerr << "error: got empty string for making TextFormat data, input: \""
+ << input_for_decode << "\", desired: \"" << desired_output << "\"."
+ << std::endl;
+ std::cerr.flush();
+ abort();
+ }
+ if ((input_for_decode.find('\0') != std::string::npos) ||
+ (desired_output.find('\0') != std::string::npos)) {
+ std::cerr << "error: got a null char in a string for making TextFormat data,"
+ << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
+ << CEscape(desired_output) << "\"." << std::endl;
+ std::cerr.flush();
+ abort();
+ }
+
+ DecodeDataBuilder builder;
+
+ // Walk the output building it from the input.
+ int x = 0;
+ for (int y = 0; y < desired_output.size(); y++) {
+ const char d = desired_output[y];
+ if (d == '_') {
+ builder.AddUnderscore();
+ continue;
+ }
+
+ if (x >= input_for_decode.size()) {
+ // Out of input, no way to encode it, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ if (builder.AddCharacter(d, input_for_decode[x])) {
+ ++x; // Consumed one input
+ } else {
+ // Couldn't transform for the next character, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ }
+
+ if (x != input_for_decode.size()) {
+ // Extra input (suffix from name sanitizing?), just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+
+ // Add the end marker.
+ return builder.Finish() + (char)'\0';
+}
+
+namespace {
+
+class Parser {
+ public:
+ Parser(LineConsumer* line_consumer)
+ : line_consumer_(line_consumer), line_(0) {}
+
+ // Feeds in some input, parse what it can, returning success/failure. Calling
+ // again after an error is undefined.
+ bool ParseChunk(StringPiece chunk, std::string* out_error);
+
+ // Should be called to finish parsing (after all input has been provided via
+ // successful calls to ParseChunk(), calling after a ParseChunk() failure is
+ // undefined). Returns success/failure.
+ bool Finish(std::string* out_error);
+
+ int last_line() const { return line_; }
+
+ private:
+ LineConsumer* line_consumer_;
+ int line_;
+ std::string leftover_;
+};
+
+bool Parser::ParseChunk(StringPiece chunk, std::string* out_error) {
+ StringPiece full_chunk;
+ if (!leftover_.empty()) {
+ leftover_ += std::string(chunk);
+ full_chunk = StringPiece(leftover_);
+ } else {
+ full_chunk = chunk;
+ }
+
+ StringPiece line;
+ while (ReadLine(&full_chunk, &line)) {
+ ++line_;
+ RemoveComment(&line);
+ TrimWhitespace(&line);
+ if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) {
+ if (out_error->empty()) {
+ *out_error = "ConsumeLine failed without setting an error.";
+ }
+ leftover_.clear();
+ return false;
+ }
+ }
+
+ if (full_chunk.empty()) {
+ leftover_.clear();
+ } else {
+ leftover_ = std::string(full_chunk);
+ }
+ return true;
+}
+
+bool Parser::Finish(std::string* out_error) {
+ // If there is still something to go, flush it with a newline.
+ if (!leftover_.empty() && !ParseChunk("\n", out_error)) {
+ return false;
+ }
+ // This really should never fail if ParseChunk succeeded, but check to be sure.
+ if (!leftover_.empty()) {
+ *out_error = "ParseSimple Internal error: finished with pending data.";
+ return false;
+ }
+ return true;
+}
+
+std::string FullErrorString(const std::string& name, int line_num, const std::string& msg) {
+ return std::string("error: ") + name + " Line " + StrCat(line_num) + ", " + msg;
+}
+
+} // namespace
+
+LineConsumer::LineConsumer() {}
+
+LineConsumer::~LineConsumer() {}
+
+bool ParseSimpleFile(const std::string& path, LineConsumer* line_consumer,
+ std::string* out_error) {
+ int fd;
+ do {
+ fd = posix::open(path.c_str(), O_RDONLY);
+ } while (fd < 0 && errno == EINTR);
+ if (fd < 0) {
+ *out_error = std::string("error: Unable to open \"") + path + "\", " +
+ strerror(errno);
+ return false;
+ }
+ io::FileInputStream file_stream(fd);
+ file_stream.SetCloseOnDelete(true);
+
+ return ParseSimpleStream(file_stream, path, line_consumer, out_error);
+}
+
+bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
+ const std::string& stream_name,
+ LineConsumer* line_consumer,
+ std::string* out_error) {
+ std::string local_error;
+ Parser parser(line_consumer);
+ const void* buf;
+ int buf_len;
+ while (input_stream.Next(&buf, &buf_len)) {
+ if (buf_len == 0) {
+ continue;
+ }
+
+ if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len),
+ &local_error)) {
+ *out_error = FullErrorString(stream_name, parser.last_line(), local_error);
+ return false;
+ }
+ }
+ if (!parser.Finish(&local_error)) {
+ *out_error = FullErrorString(stream_name, parser.last_line(), local_error);
+ return false;
+ }
+ return true;
+}
+
+ImportWriter::ImportWriter(
+ const std::string& generate_for_named_framework,
+ const std::string& named_framework_to_proto_path_mappings_path,
+ const std::string& runtime_import_prefix, bool include_wkt_imports)
+ : generate_for_named_framework_(generate_for_named_framework),
+ named_framework_to_proto_path_mappings_path_(
+ named_framework_to_proto_path_mappings_path),
+ runtime_import_prefix_(runtime_import_prefix),
+ include_wkt_imports_(include_wkt_imports),
+ need_to_parse_mapping_file_(true) {}
+
+ImportWriter::~ImportWriter() {}
+
+void ImportWriter::AddFile(const FileDescriptor* file,
+ const std::string& header_extension) {
+ if (IsProtobufLibraryBundledProtoFile(file)) {
+ // The imports of the WKTs are only needed within the library itself,
+ // in other cases, they get skipped because the generated code already
+ // import GPBProtocolBuffers.h and hence proves them.
+ if (include_wkt_imports_) {
+ const std::string header_name =
+ "GPB" + FilePathBasename(file) + header_extension;
+ protobuf_imports_.push_back(header_name);
+ }
+ return;
+ }
+
+ // Lazy parse any mappings.
+ if (need_to_parse_mapping_file_) {
+ ParseFrameworkMappings();
+ }
+
+ std::map<std::string, std::string>::iterator proto_lookup =
+ proto_file_to_framework_name_.find(file->name());
+ if (proto_lookup != proto_file_to_framework_name_.end()) {
+ other_framework_imports_.push_back(
+ proto_lookup->second + "/" +
+ FilePathBasename(file) + header_extension);
+ return;
+ }
+
+ if (!generate_for_named_framework_.empty()) {
+ other_framework_imports_.push_back(
+ generate_for_named_framework_ + "/" +
+ FilePathBasename(file) + header_extension);
+ return;
+ }
+
+ other_imports_.push_back(FilePath(file) + header_extension);
+}
+
+void ImportWriter::Print(io::Printer* printer) const {
+ bool add_blank_line = false;
+
+ if (!protobuf_imports_.empty()) {
+ PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_);
+ add_blank_line = true;
+ }
+
+ if (!other_framework_imports_.empty()) {
+ if (add_blank_line) {
+ printer->Print("\n");
+ }
+
+ for (std::vector<std::string>::const_iterator iter =
+ other_framework_imports_.begin();
+ iter != other_framework_imports_.end(); ++iter) {
+ printer->Print(
+ "#import <$header$>\n",
+ "header", *iter);
+ }
+
+ add_blank_line = true;
+ }
+
+ if (!other_imports_.empty()) {
+ if (add_blank_line) {
+ printer->Print("\n");
+ }
+
+ for (std::vector<std::string>::const_iterator iter = other_imports_.begin();
+ iter != other_imports_.end(); ++iter) {
+ printer->Print(
+ "#import \"$header$\"\n",
+ "header", *iter);
+ }
+ }
+}
+
+void ImportWriter::PrintRuntimeImports(
+ io::Printer* printer, const std::vector<std::string>& header_to_import,
+ const std::string& runtime_import_prefix, bool default_cpp_symbol) {
+ // Given an override, use that.
+ if (!runtime_import_prefix.empty()) {
+ for (const auto& header : header_to_import) {
+ printer->Print(
+ " #import \"$import_prefix$/$header$\"\n",
+ "import_prefix", runtime_import_prefix,
+ "header", header);
+ }
+ return;
+ }
+
+ const std::string framework_name(ProtobufLibraryFrameworkName);
+ const std::string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+ if (default_cpp_symbol) {
+ printer->Print(
+ "// This CPP symbol can be defined to use imports that match up to the framework\n"
+ "// imports needed when using CocoaPods.\n"
+ "#if !defined($cpp_symbol$)\n"
+ " #define $cpp_symbol$ 0\n"
+ "#endif\n"
+ "\n",
+ "cpp_symbol", cpp_symbol);
+ }
+
+ printer->Print(
+ "#if $cpp_symbol$\n",
+ "cpp_symbol", cpp_symbol);
+ for (const auto& header : header_to_import) {
+ printer->Print(
+ " #import <$framework_name$/$header$>\n",
+ "framework_name", framework_name,
+ "header", header);
+ }
+ printer->Print(
+ "#else\n");
+ for (const auto& header : header_to_import) {
+ printer->Print(
+ " #import \"$header$\"\n",
+ "header", header);
+ }
+ printer->Print(
+ "#endif\n");
+}
+
+void ImportWriter::ParseFrameworkMappings() {
+ need_to_parse_mapping_file_ = false;
+ if (named_framework_to_proto_path_mappings_path_.empty()) {
+ return; // Nothing to do.
+ }
+
+ ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
+ std::string parse_error;
+ if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
+ &collector, &parse_error)) {
+ std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
+ << " : " << parse_error << std::endl;
+ std::cerr.flush();
+ }
+}
+
+bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
+ const StringPiece& line, std::string* out_error) {
+ int offset = line.find(':');
+ if (offset == StringPiece::npos) {
+ *out_error =
+ std::string("Framework/proto file mapping line without colon sign: '") +
+ std::string(line) + "'.";
+ return false;
+ }
+ StringPiece framework_name = line.substr(0, offset);
+ StringPiece proto_file_list = line.substr(offset + 1);
+ TrimWhitespace(&framework_name);
+
+ int start = 0;
+ while (start < proto_file_list.length()) {
+ offset = proto_file_list.find(',', start);
+ if (offset == StringPiece::npos) {
+ offset = proto_file_list.length();
+ }
+
+ StringPiece proto_file = proto_file_list.substr(start, offset - start);
+ TrimWhitespace(&proto_file);
+ if (!proto_file.empty()) {
+ std::map<std::string, std::string>::iterator existing_entry =
+ map_->find(std::string(proto_file));
+ if (existing_entry != map_->end()) {
+ std::cerr << "warning: duplicate proto file reference, replacing "
+ "framework entry for '"
+ << std::string(proto_file) << "' with '" << std::string(framework_name)
+ << "' (was '" << existing_entry->second << "')." << std::endl;
+ std::cerr.flush();
+ }
+
+ if (proto_file.find(' ') != StringPiece::npos) {
+ std::cerr << "note: framework mapping file had a proto file with a "
+ "space in, hopefully that isn't a missing comma: '"
+ << std::string(proto_file) << "'" << std::endl;
+ std::cerr.flush();
+ }
+
+ (*map_)[std::string(proto_file)] = std::string(framework_name);
+ }
+
+ start = offset + 1;
+ }
+
+ return true;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h
new file mode 100644
index 00000000..e6a3e436
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -0,0 +1,347 @@
+// 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.
+
+// Helper functions for generating ObjectiveC code.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+
+#include <string>
+#include <vector>
+
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/zero_copy_stream.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Get/Set if the proto package should be used to make the default prefix for
+// symbols. This will then impact most of the type naming apis below. It is done
+// as a global to not break any other generator reusing the methods since they
+// are exported.
+bool PROTOC_EXPORT UseProtoPackageAsDefaultPrefix();
+void PROTOC_EXPORT SetUseProtoPackageAsDefaultPrefix(bool on_or_off);
+// Get/Set the path to a file to load as exceptions when
+// `UseProtoPackageAsDefaultPrefixUseProtoPackageAsDefaultPrefix()` is `true`.
+// And empty string means there should be no exceptions loaded.
+std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList();
+void PROTOC_EXPORT SetProtoPackagePrefixExceptionList(
+ const std::string& file_path);
+
+// Generator options (see objectivec_generator.cc for a description of each):
+struct Options {
+ Options();
+ std::string expected_prefixes_path;
+ std::vector<std::string> expected_prefixes_suppressions;
+ std::string generate_for_named_framework;
+ std::string named_framework_to_proto_path_mappings_path;
+ std::string runtime_import_prefix;
+ bool prefixes_must_be_registered;
+ bool require_prefixes;
+};
+
+// Escape C++ trigraphs by escaping question marks to "\?".
+std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape);
+
+// Remove white space from either end of a StringPiece.
+void PROTOC_EXPORT TrimWhitespace(StringPiece* input);
+
+// Returns true if the name requires a ns_returns_not_retained attribute applied
+// to it.
+bool PROTOC_EXPORT IsRetainedName(const std::string& name);
+
+// Returns true if the name starts with "init" and will need to have special
+// handling under ARC.
+bool PROTOC_EXPORT IsInitName(const std::string& name);
+
+// Gets the objc_class_prefix or the prefix made from the proto package.
+std::string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file);
+
+// Gets the path of the file we're going to generate (sans the .pb.h
+// extension). The path will be dependent on the objectivec package
+// declared in the proto package.
+std::string PROTOC_EXPORT FilePath(const FileDescriptor* file);
+
+// Just like FilePath(), but without the directory part.
+std::string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file);
+
+// Gets the name of the root class we'll generate in the file. This class
+// is not meant for external consumption, but instead contains helpers that
+// the rest of the classes need
+std::string PROTOC_EXPORT FileClassName(const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor);
+std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor,
+ std::string* out_suffix_added);
+std::string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor);
+
+// Returns the fully-qualified name of the enum value corresponding to the
+// the descriptor.
+std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
+
+// Returns the name of the enum value corresponding to the descriptor.
+std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
+
+// Reverse what an enum does.
+std::string PROTOC_EXPORT UnCamelCaseEnumShortName(const std::string& name);
+
+// Returns the name to use for the extension (used as the method off the file's
+// Root class).
+std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
+
+// Returns the transformed field name.
+std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field);
+std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
+
+// Returns the transformed oneof name.
+std::string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
+std::string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
+std::string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
+
+// Returns a symbol that can be used in C code to refer to an Objective C
+// class without initializing the class.
+std::string PROTOC_EXPORT ObjCClass(const std::string& class_name);
+
+// Declares an Objective C class without initializing the class so that it can
+// be refrerred to by ObjCClass.
+std::string PROTOC_EXPORT ObjCClassDeclaration(const std::string& class_name);
+
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+// Reverse of the above.
+std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name,
+ const FieldDescriptor* field);
+
+enum ObjectiveCType {
+ OBJECTIVECTYPE_INT32,
+ OBJECTIVECTYPE_UINT32,
+ OBJECTIVECTYPE_INT64,
+ OBJECTIVECTYPE_UINT64,
+ OBJECTIVECTYPE_FLOAT,
+ OBJECTIVECTYPE_DOUBLE,
+ OBJECTIVECTYPE_BOOLEAN,
+ OBJECTIVECTYPE_STRING,
+ OBJECTIVECTYPE_DATA,
+ OBJECTIVECTYPE_ENUM,
+ OBJECTIVECTYPE_MESSAGE
+};
+
+enum FlagType {
+ FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ FLAGTYPE_EXTENSION,
+ FLAGTYPE_FIELD
+};
+
+template <class TDescriptor>
+std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor,
+ const FileDescriptor* file = NULL,
+ bool preSpace = true,
+ bool postNewline = false) {
+ bool isDeprecated = descriptor->options().deprecated();
+ // The file is only passed when checking Messages & Enums, so those types
+ // get tagged. At the moment, it doesn't seem to make sense to tag every
+ // field or enum value with when the file is deprecated.
+ bool isFileLevelDeprecation = false;
+ if (!isDeprecated && file) {
+ isFileLevelDeprecation = file->options().deprecated();
+ isDeprecated = isFileLevelDeprecation;
+ }
+ if (isDeprecated) {
+ std::string message;
+ const FileDescriptor* sourceFile = descriptor->file();
+ if (isFileLevelDeprecation) {
+ message = sourceFile->name() + " is deprecated.";
+ } else {
+ message = descriptor->full_name() + " is deprecated (see " +
+ sourceFile->name() + ").";
+ }
+
+ std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")";
+ if (preSpace) {
+ result.insert(0, " ");
+ }
+ if (postNewline) {
+ result.append("\n");
+ }
+ return result;
+ } else {
+ return "";
+ }
+}
+
+std::string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType PROTOC_EXPORT
+GetObjectiveCType(FieldDescriptor::Type field_type);
+
+inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
+ return GetObjectiveCType(field->type());
+}
+
+bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field);
+bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field);
+
+std::string PROTOC_EXPORT
+GPBGenericValueFieldName(const FieldDescriptor* field);
+std::string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field);
+bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field);
+
+std::string PROTOC_EXPORT
+BuildFlagsString(const FlagType type, const std::vector<std::string>& strings);
+
+// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
+// file.
+std::string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location,
+ bool prefer_single_line);
+
+// The name the commonly used by the library when built as a framework.
+// This lines up to the name used in the CocoaPod.
+extern PROTOC_EXPORT const char* const ProtobufLibraryFrameworkName;
+// Returns the CPP symbol name to use as the gate for framework style imports
+// for the given framework name to use.
+std::string PROTOC_EXPORT
+ProtobufFrameworkImportSymbol(const std::string& framework_name);
+
+// Checks if the file is one of the proto's bundled with the library.
+bool PROTOC_EXPORT
+IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
+
+// Checks the prefix for the given files and outputs any warnings as needed. If
+// there are flat out errors, then out_error is filled in with the first error
+// and the result is false.
+bool PROTOC_EXPORT ValidateObjCClassPrefixes(
+ const std::vector<const FileDescriptor*>& files,
+ const Options& generation_options, std::string* out_error);
+
+// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
+// the input into the expected output.
+class PROTOC_EXPORT TextFormatDecodeData {
+ public:
+ TextFormatDecodeData();
+ ~TextFormatDecodeData();
+
+ TextFormatDecodeData(const TextFormatDecodeData&) = delete;
+ TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete;
+
+ void AddString(int32_t key, const std::string& input_for_decode,
+ const std::string& desired_output);
+ size_t num_entries() const { return entries_.size(); }
+ std::string Data() const;
+
+ static std::string DecodeDataForString(const std::string& input_for_decode,
+ const std::string& desired_output);
+
+ private:
+ typedef std::pair<int32_t, std::string> DataEntry;
+ std::vector<DataEntry> entries_;
+};
+
+// Helper for parsing simple files.
+class PROTOC_EXPORT LineConsumer {
+ public:
+ LineConsumer();
+ virtual ~LineConsumer();
+ virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0;
+};
+
+bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,
+ LineConsumer* line_consumer,
+ std::string* out_error);
+
+bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
+ const std::string& stream_name,
+ LineConsumer* line_consumer,
+ std::string* out_error);
+
+// Helper class for parsing framework import mappings and generating
+// import statements.
+class PROTOC_EXPORT ImportWriter {
+ public:
+ ImportWriter(const std::string& generate_for_named_framework,
+ const std::string& named_framework_to_proto_path_mappings_path,
+ const std::string& runtime_import_prefix,
+ bool include_wkt_imports);
+ ~ImportWriter();
+
+ void AddFile(const FileDescriptor* file, const std::string& header_extension);
+ void Print(io::Printer* printer) const;
+
+ static void PrintRuntimeImports(io::Printer* printer,
+ const std::vector<std::string>& header_to_import,
+ const std::string& runtime_import_prefix,
+ bool default_cpp_symbol = false);
+
+ private:
+ class ProtoFrameworkCollector : public LineConsumer {
+ public:
+ ProtoFrameworkCollector(std::map<std::string, std::string>* inout_proto_file_to_framework_name)
+ : map_(inout_proto_file_to_framework_name) {}
+
+ virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
+
+ private:
+ std::map<std::string, std::string>* map_;
+ };
+
+ void ParseFrameworkMappings();
+
+ const std::string generate_for_named_framework_;
+ const std::string named_framework_to_proto_path_mappings_path_;
+ const std::string runtime_import_prefix_;
+ const bool include_wkt_imports_;
+ std::map<std::string, std::string> proto_file_to_framework_name_;
+ bool need_to_parse_mapping_file_;
+
+ std::vector<std::string> protobuf_imports_;
+ std::vector<std::string> other_framework_imports_;
+ std::vector<std::string> other_imports_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
new file mode 100644
index 00000000..85f150b9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -0,0 +1,385 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/zero_copy_stream_impl_lite.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
+ std::string input_for_decode("abcdefghIJ");
+ std::string desired_output_for_decode;
+ std::string expected;
+ std::string result;
+
+ // Different data, can't transform.
+
+ desired_output_for_decode = "zbcdefghIJ";
+ expected = std::string("\0zbcdefghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "abcdezghIJ";
+ expected = std::string("\0abcdezghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Shortened data, can't transform.
+
+ desired_output_for_decode = "abcdefghI";
+ expected = std::string("\0abcdefghI\0", 11);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Extra data, can't transform.
+
+ desired_output_for_decode = "abcdefghIJz";
+ expected = std::string("\0abcdefghIJz\0", 13);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
+ std::string input_for_decode("abcdefghIJ");
+ std::string desired_output_for_decode;
+ std::string expected;
+ std::string result;
+
+ desired_output_for_decode = "abcdefghIJ";
+ expected = std::string("\x0A\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "_AbcdefghIJ";
+ expected = std::string("\xCA\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "ABCD__EfghI_j";
+ expected = std::string("\x64\x80\xC5\xA1\x0", 5);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Long name so multiple decode ops are needed.
+
+ input_for_decode =
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+ desired_output_for_decode =
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
+ expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
+ // Empty inputs.
+
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ std::string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
+TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
+ TextFormatDecodeData decode_data;
+
+ // Different data, can't transform.
+ decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
+ // Shortened data, can't transform.
+ decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
+ // Extra data, can't transform.
+ decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
+
+ EXPECT_EQ(4, decode_data.num_entries());
+
+ uint8 expected_data[] = {
+ 0x4,
+ 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+ 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
+ 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
+ 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
+ };
+ std::string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
+ TextFormatDecodeData decode_data;
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
+ decode_data.AddString(1000,
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+
+ EXPECT_EQ(5, decode_data.num_entries());
+
+ uint8 expected_data[] = {
+ 0x5,
+ // All as is (00 op)
+ 0x1, 0x0A, 0x0,
+ // Underscore, upper + 9 (10 op)
+ 0x3, 0xCA, 0x0,
+ // Upper + 3 (10 op), underscore, upper + 5 (10 op)
+ 0x2, 0x44, 0xC6, 0x0,
+ // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+ // underscore, lower + 0 (01 op)
+ 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+ // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+ // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+ // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
+ // op),
+ // underscore, as is + 3 (00 op)
+ 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+ };
+ std::string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+
+// Death tests do not work on Windows as of yet.
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
+ TextFormatDecodeData decode_data;
+
+ // Empty inputs.
+
+ EXPECT_EXIT(decode_data.AddString(1, "", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ std::string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ decode_data.AddString(1, str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ decode_data.AddString(1, "def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+
+ // Duplicate keys
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: duplicate key \\(2\\) making TextFormat data, input:");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
+class TestLineCollector : public LineConsumer {
+ public:
+ TestLineCollector(std::vector<std::string>* inout_lines,
+ const std::string* reject_line = nullptr,
+ bool skip_msg = false)
+ : lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
+
+ bool ConsumeLine(const StringPiece& line, std::string* out_error) override {
+ if (reject_ && *reject_ == line) {
+ if (!skip_msg_) {
+ *out_error = std::string("Rejected '") + *reject_ + "'";
+ }
+ return false;
+ }
+ if (lines_) {
+ lines_->emplace_back(line);
+ }
+ return true;
+ }
+
+ private:
+ std::vector<std::string>* lines_;
+ const std::string* reject_;
+ bool skip_msg_;
+};
+
+const int kBlockSizes[] = {-1, 1, 2, 5, 64};
+const int kBlockSizeCount = GOOGLE_ARRAYSIZE(kBlockSizes);
+
+TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
+ const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
+ {"", {}},
+ {"a", {"a"}},
+ {"a c", {"a c"}},
+ {" a c ", {"a c"}},
+ {"\ta c ", {"a c"}},
+ {"abc\n", {"abc"}},
+ {"abc\nd f", {"abc", "d f"}},
+ {"\n abc \n def \n\n", {"abc", "def"}},
+ };
+
+ for (const auto& test : tests) {
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
+ std::string err_str;
+ std::vector<std::string> lines;
+ TestLineCollector collector(&lines);
+ EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+ EXPECT_EQ(lines, test.second);
+ EXPECT_TRUE(err_str.empty());
+ }
+ }
+}
+
+TEST(ObjCHelper, ParseSimple_DropsComments) {
+ const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
+ {"# nothing", {}},
+ {"#", {}},
+ {"##", {}},
+ {"\n# nothing\n", {}},
+ {"a # same line", {"a"}},
+ {"a # same line\n", {"a"}},
+ {"a\n# line\nc", {"a", "c"}},
+ {"# n o t # h i n g #", {}},
+ {"## n o # t h i n g #", {}},
+ {"a# n o t # h i n g #", {"a"}},
+ {"a\n## n o # t h i n g #", {"a"}},
+ };
+
+ for (const auto& test : tests) {
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
+ std::string err_str;
+ std::vector<std::string> lines;
+ TestLineCollector collector(&lines);
+ EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+ EXPECT_EQ(lines, test.second);
+ EXPECT_TRUE(err_str.empty());
+ }
+ }
+}
+
+TEST(ObjCHelper, ParseSimple_RejectLines) {
+ const std::vector<std::tuple<std::string, std::string, int>> tests = {
+ std::make_tuple("a\nb\nc", "a", 1),
+ std::make_tuple("a\nb\nc", "b", 2),
+ std::make_tuple("a\nb\nc", "c", 3),
+ std::make_tuple("a\nb\nc\n", "c", 3),
+ };
+
+ for (const auto& test : tests) {
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
+ kBlockSizes[i]);
+ std::string err_str;
+ TestLineCollector collector(nullptr, &std::get<1>(test));
+ EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+ std::string expected_err =
+ StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '", std::get<1>(test), "'");
+ EXPECT_EQ(err_str, expected_err);
+ }
+ }
+}
+
+TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) {
+ const std::vector<std::tuple<std::string, std::string, int>> tests = {
+ std::make_tuple("a\nb\nc", "a", 1),
+ std::make_tuple("a\nb\nc", "b", 2),
+ std::make_tuple("a\nb\nc", "c", 3),
+ std::make_tuple("a\nb\nc\n", "c", 3),
+ };
+
+ for (const auto& test : tests) {
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
+ kBlockSizes[i]);
+ std::string err_str;
+ TestLineCollector collector(nullptr, &std::get<1>(test), true /* skip msg */);
+ EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+ std::string expected_err =
+ StrCat("error: dummy Line ", std::get<2>(test),
+ ", ConsumeLine failed without setting an error.");
+ EXPECT_EQ(err_str, expected_err);
+ }
+ }
+}
+
+// TODO(thomasvl): Should probably add some unittests for all the special cases
+// of name mangling (class name, field name, enum names). Rather than doing
+// this with an ObjC test in the objectivec directory, we should be able to
+// use src/google/protobuf/compiler/importer* (like other tests) to support a
+// virtual file system to feed in protos, once we have the Descriptor tree, the
+// tests could use the helper methods for generating names and validate the
+// right things are happening.
+
+} // namespace
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc
new file mode 100644
index 00000000..58681ae4
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -0,0 +1,189 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_map_field.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it
+// provides a bunch of things (no has* methods, comments for contained type,
+// etc.).
+
+namespace {
+
+const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return (isKey ? "String" : "Object");
+ case OBJECTIVECTYPE_DATA:
+ return "Object";
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ return "Object";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+} // namespace
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
+ const FieldDescriptor* key_descriptor =
+ descriptor->message_type()->map_key();
+ const FieldDescriptor* value_descriptor =
+ descriptor->message_type()->map_value();
+ value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
+
+ // Pull over some variables_ from the value.
+ variables_["field_type"] = value_field_generator_->variable("field_type");
+ variables_["default"] = value_field_generator_->variable("default");
+ variables_["default_name"] = value_field_generator_->variable("default_name");
+
+ // Build custom field flags.
+ std::vector<std::string> field_flags;
+ field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
+ // Pull over the current text format custom name values that was calculated.
+ if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
+ std::string::npos) {
+ field_flags.push_back("GPBFieldTextFormatNameCustom");
+ }
+ // Pull over some info from the value's flags.
+ const std::string& value_field_flags =
+ value_field_generator_->variable("fieldflags");
+ if (value_field_flags.find("GPBFieldHasDefaultValue") != std::string::npos) {
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ }
+ if (value_field_flags.find("GPBFieldHasEnumDescriptor") !=
+ std::string::npos) {
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+
+ variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
+
+ ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+ const bool value_is_object_type =
+ ((value_objc_type == OBJECTIVECTYPE_STRING) ||
+ (value_objc_type == OBJECTIVECTYPE_DATA) ||
+ (value_objc_type == OBJECTIVECTYPE_MESSAGE));
+ if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+ value_is_object_type) {
+ variables_["array_storage_type"] = "NSMutableDictionary";
+ variables_["array_property_type"] =
+ "NSMutableDictionary<NSString*, " +
+ value_field_generator_->variable("storage_type") + "*>";
+ } else {
+ std::string class_name("GPB");
+ class_name += MapEntryTypeName(key_descriptor, true);
+ class_name += MapEntryTypeName(value_descriptor, false);
+ class_name += "Dictionary";
+ variables_["array_storage_type"] = class_name;
+ if (value_is_object_type) {
+ variables_["array_property_type"] =
+ class_name + "<" +
+ value_field_generator_->variable("storage_type") + "*>";
+ }
+ }
+
+ variables_["dataTypeSpecific_name"] =
+ value_field_generator_->variable("dataTypeSpecific_name");
+ variables_["dataTypeSpecific_value"] =
+ value_field_generator_->variable("dataTypeSpecific_value");
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ // Use the array_comment support in RepeatedFieldGenerator to output what the
+ // values in the map are.
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+ }
+}
+
+void MapFieldGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const {
+ RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+ const std::string& value_storage_type =
+ value_field_generator_->variable("storage_type");
+ fwd_decls->insert("@class " + value_storage_type);
+ }
+}
+
+void MapFieldGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const {
+ // Class name is already in "storage_type".
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+ fwd_decls->insert(ObjCClassDeclaration(
+ value_field_generator_->variable("storage_type")));
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h
new file mode 100644
index 00000000..32371123
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MapFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ public:
+ virtual void FinishInitialization(void) override;
+
+ MapFieldGenerator(const MapFieldGenerator&) = delete;
+ MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
+
+ protected:
+ MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+ virtual ~MapFieldGenerator();
+
+ virtual void DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const override;
+ virtual void DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const override;
+
+ private:
+ std::unique_ptr<FieldGenerator> value_field_generator_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc
new file mode 100644
index 00000000..0e8bfec9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc
@@ -0,0 +1,636 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <compiler/objectivec/objectivec_message.h>
+#include <compiler/objectivec/objectivec_enum.h>
+#include <compiler/objectivec/objectivec_extension.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <stubs/stl_util.h>
+#include <stubs/strutil.h>
+#include <io/printer.h>
+#include <io/coded_stream.h>
+#include <io/zero_copy_stream_impl.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+#include <descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+ // The first item in the object structure is our uint32[] for has bits.
+ // We then want to order things to make the instances as small as
+ // possible. So we follow the has bits with:
+ // 1. Anything always 4 bytes - float, *32, enums
+ // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit
+ // builds and 4 bytes on 32bit builds.
+ // 3. Anything always 8 bytes - double, *64
+ //
+ // NOTE: Bools aren't listed, they were stored in the has bits.
+ //
+ // Why? Using 64bit builds as an example, this means worse case, we have
+ // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+ // are wasted before the 4 byte values. Then if we have an odd number of
+ // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+ // keep them aligned. But the structure will end 8 byte aligned, so no
+ // waste on the end. If you did the reverse order, you could waste 4 bytes
+ // before the first 8 byte value (after the has array), then a single
+ // bool on the end would need 7 bytes of padding to make the overall
+ // structure 8 byte aligned; so 11 bytes, wasted total.
+
+ // Anything repeated is a GPB*Array/NSArray, so pointer.
+ if (descriptor->is_repeated()) {
+ return 3;
+ }
+
+ switch (descriptor->type()) {
+ // All always 8 bytes.
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return 4;
+
+ // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+ // depending on the build architecture.
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return 3;
+
+ // All always 4 bytes (enums are int32s).
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_ENUM:
+ return 2;
+
+ // 0 bytes. Stored in the has bits.
+ case FieldDescriptor::TYPE_BOOL:
+ return 99; // End of the list (doesn't really matter).
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
+}
+
+struct FieldOrderingByStorageSize {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ // Order by grouping.
+ const int order_group_a = OrderGroupForFieldDescriptor(a);
+ const int order_group_b = OrderGroupForFieldDescriptor(b);
+ if (order_group_a != order_group_b) {
+ return order_group_a < order_group_b;
+ }
+ // Within the group, order by field number (provides stable ordering).
+ return a->number() < b->number();
+ }
+};
+
+struct ExtensionRangeOrdering {
+ bool operator()(const Descriptor::ExtensionRange* a,
+ const Descriptor::ExtensionRange* b) const {
+ return a->start < b->start;
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+ return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByStorageSize());
+ return fields;
+}
+} // namespace
+
+MessageGenerator::MessageGenerator(const std::string& root_classname,
+ const Descriptor* descriptor,
+ const Options& options)
+ : root_classname_(root_classname),
+ descriptor_(descriptor),
+ field_generators_(descriptor, options),
+ class_name_(ClassName(descriptor_)),
+ deprecated_attribute_(GetOptionalDeprecatedAttribute(
+ descriptor, descriptor->file(), false, true)) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_.emplace_back(
+ new ExtensionGenerator(class_name_, descriptor_->extension(i)));
+ }
+
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+ oneof_generators_.emplace_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
+ enum_generators_.emplace_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ MessageGenerator* generator =
+ new MessageGenerator(root_classname_,
+ descriptor_->nested_type(i),
+ options);
+ nested_message_generators_.emplace_back(generator);
+ }
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+void MessageGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer) {
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+}
+
+void MessageGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+ field_generators_.get(fieldDescriptor)
+ .DetermineForwardDeclarations(fwd_decls);
+ }
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->DetermineForwardDeclarations(fwd_decls);
+ }
+}
+
+void MessageGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+ field_generators_.get(fieldDescriptor)
+ .DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+ }
+
+ for (const auto& generator : extension_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+
+ const Descriptor* containing_descriptor = descriptor_->containing_type();
+ if (containing_descriptor != NULL) {
+ std::string containing_class = ClassName(containing_descriptor);
+ fwd_decls->insert(ObjCClassDeclaration(containing_class));
+ }
+}
+
+bool MessageGenerator::IncludesOneOfDefinition() const {
+ if (!oneof_generators_.empty()) {
+ return true;
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ if (generator->IncludesOneOfDefinition()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateHeader(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateEnumHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateExtensionRegistrationSource(
+ io::Printer* printer) {
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateRegistrationSource(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateExtensionRegistrationSource(printer);
+ }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
+ // This a a map entry message, just recurse and do nothing directly.
+ if (IsMapEntryMessage(descriptor_)) {
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateMessageHeader(printer);
+ }
+ return;
+ }
+
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (descriptor_->field_count()) {
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+ "classname", class_name_);
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i])
+ .GenerateFieldNumberConstant(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("};\n\n");
+ }
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateCaseEnum(printer);
+ }
+
+ std::string message_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ message_comments = BuildCommentsString(location, false);
+ } else {
+ message_comments = "";
+ }
+
+ printer->Print(
+ "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
+ "classname", class_name_,
+ "deprecated_attribute", deprecated_attribute_,
+ "comments", message_comments);
+
+ std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const OneofDescriptor* oneof = field->real_containing_oneof();
+ if (oneof) {
+ const int oneof_index = oneof->index();
+ if (!seen_oneofs[oneof_index]) {
+ seen_oneofs[oneof_index] = 1;
+ oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+ printer);
+ }
+ }
+ field_generators_.get(field).GeneratePropertyDeclaration(printer);
+ }
+
+ printer->Print("@end\n\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionDeclarations(printer);
+ }
+
+ if (!oneof_generators_.empty()) {
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateClearFunctionDeclaration(printer);
+ }
+ printer->Print("\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+ "classname", class_name_);
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateMembersHeader(printer);
+ }
+ printer->Print("@end\n\n");
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateMessageHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (!deprecated_attribute_.empty()) {
+ // No warnings when compiling the impl of this deprecated class.
+ printer->Print(
+ "#pragma clang diagnostic push\n"
+ "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
+ "\n");
+ }
+
+ printer->Print("@implementation $classname$\n\n",
+ "classname", class_name_);
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GeneratePropertyImplementation(printer);
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GeneratePropertyImplementation(printer);
+ }
+
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
+ SortFieldsByStorageSize(descriptor_));
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ // Assign has bits:
+ // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
+ // who needs has bits and assigning them.
+ // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+ // index that groups all the elements in the oneof.
+ size_t num_has_bits = field_generators_.CalculateHasBits();
+ size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+ if (sizeof_has_storage == 0) {
+ // In the case where no field needs has bits, don't let the _has_storage_
+ // end up as zero length (zero length arrays are sort of a grey area
+ // since it has to be at the start of the struct). This also ensures a
+ // field with only oneofs keeps the required negative indices they need.
+ sizeof_has_storage = 1;
+ }
+ // Tell all the fields the oneof base.
+ for (const auto& generator : oneof_generators_) {
+ generator->SetOneofIndexBase(sizeof_has_storage);
+ }
+ field_generators_.SetOneofIndexBase(sizeof_has_storage);
+ // sizeof_has_storage needs enough bits for the single fields that aren't in
+ // any oneof, and then one int32 for each oneof (to store the field number).
+ sizeof_has_storage += oneof_generators_.size();
+
+ printer->Print(
+ "\n"
+ "typedef struct $classname$__storage_ {\n"
+ " uint32_t _has_storage_[$sizeof_has_storage$];\n",
+ "classname", class_name_,
+ "sizeof_has_storage", StrCat(sizeof_has_storage));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(size_order_fields[i])
+ .GenerateFieldStorageDeclaration(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
+
+
+ printer->Print(
+ "// This method is threadsafe because it is initially called\n"
+ "// in +initialize for each subclass.\n"
+ "+ (GPBDescriptor *)descriptor {\n"
+ " static GPBDescriptor *descriptor = nil;\n"
+ " if (!descriptor) {\n");
+
+ TextFormatDecodeData text_format_decode_data;
+ bool has_fields = descriptor_->field_count() > 0;
+ bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+ std::string field_description_type;
+ if (need_defaults) {
+ field_description_type = "GPBMessageFieldDescriptionWithDefault";
+ } else {
+ field_description_type = "GPBMessageFieldDescription";
+ }
+ if (has_fields) {
+ printer->Indent();
+ printer->Indent();
+ printer->Print(
+ "static $field_description_type$ fields[] = {\n",
+ "field_description_type", field_description_type);
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ const FieldGenerator& field_generator =
+ field_generators_.get(sorted_fields[i]);
+ field_generator.GenerateFieldDescription(printer, need_defaults);
+ if (field_generator.needs_textformat_name_support()) {
+ text_format_decode_data.AddString(sorted_fields[i]->number(),
+ field_generator.generated_objc_name(),
+ field_generator.raw_field_name());
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n");
+ printer->Outdent();
+ printer->Outdent();
+ }
+
+ std::map<std::string, std::string> vars;
+ vars["classname"] = class_name_;
+ vars["rootclassname"] = root_classname_;
+ vars["fields"] = has_fields ? "fields" : "NULL";
+ if (has_fields) {
+ vars["fields_count"] =
+ "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
+ } else {
+ vars["fields_count"] = "0";
+ }
+
+ std::vector<std::string> init_flags;
+ init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
+ init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
+ if (need_defaults) {
+ init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
+ }
+ if (descriptor_->options().message_set_wire_format()) {
+ init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
+ }
+ vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ init_flags);
+
+ printer->Print(
+ vars,
+ " GPBDescriptor *localDescriptor =\n"
+ " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+ " rootClass:[$rootclassname$ class]\n"
+ " file:$rootclassname$_FileDescriptor()\n"
+ " fields:$fields$\n"
+ " fieldCount:$fields_count$\n"
+ " storageSize:sizeof($classname$__storage_)\n"
+ " flags:$init_flags$];\n");
+ if (!oneof_generators_.empty()) {
+ printer->Print(
+ " static const char *oneofs[] = {\n");
+ for (const auto& generator : oneof_generators_) {
+ printer->Print(" \"$name$\",\n", "name",
+ generator->DescriptorName());
+ }
+ printer->Print(
+ " };\n"
+ " [localDescriptor setupOneofs:oneofs\n"
+ " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
+ " firstHasIndex:$first_has_index$];\n",
+ "first_has_index", oneof_generators_[0]->HasIndexAsString());
+ }
+ if (text_format_decode_data.num_entries() != 0) {
+ const std::string text_format_data_str(text_format_decode_data.Data());
+ printer->Print(
+ "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+ " static const char *extraTextFormatInfo =");
+ static const int kBytesPerLine = 40; // allow for escaping
+ for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
+ printer->Print(
+ "\n \"$data$\"",
+ "data", EscapeTrigraphs(
+ CEscape(text_format_data_str.substr(i, kBytesPerLine))));
+ }
+ printer->Print(
+ ";\n"
+ " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+ "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
+ }
+ if (!sorted_extensions.empty()) {
+ printer->Print(
+ " static const GPBExtensionRange ranges[] = {\n");
+ for (int i = 0; i < sorted_extensions.size(); i++) {
+ printer->Print(" { .start = $start$, .end = $end$ },\n",
+ "start", StrCat(sorted_extensions[i]->start),
+ "end", StrCat(sorted_extensions[i]->end));
+ }
+ printer->Print(
+ " };\n"
+ " [localDescriptor setupExtensionRanges:ranges\n"
+ " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+ }
+ if (descriptor_->containing_type() != NULL) {
+ std::string containing_class = ClassName(descriptor_->containing_type());
+ std::string parent_class_ref = ObjCClass(containing_class);
+ printer->Print(
+ " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
+ "parent_class_ref", parent_class_ref);
+ }
+ std::string suffix_added;
+ ClassName(descriptor_, &suffix_added);
+ if (!suffix_added.empty()) {
+ printer->Print(
+ " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+ "suffix", suffix_added);
+ }
+ printer->Print(
+ " #if defined(DEBUG) && DEBUG\n"
+ " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+ " #endif // DEBUG\n"
+ " descriptor = localDescriptor;\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n"
+ "@end\n\n");
+
+ if (!deprecated_attribute_.empty()) {
+ printer->Print(
+ "#pragma clang diagnostic pop\n"
+ "\n");
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionImplementations(printer);
+ }
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateClearFunctionImplementation(printer);
+ }
+ }
+
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateSource(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateSource(printer);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h
new file mode 100644
index 00000000..64c7b49f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <compiler/objectivec/objectivec_field.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <compiler/objectivec/objectivec_oneof.h>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator;
+class EnumGenerator;
+
+class MessageGenerator {
+ public:
+ MessageGenerator(const std::string& root_classname,
+ const Descriptor* descriptor, const Options& options);
+ ~MessageGenerator();
+
+ MessageGenerator(const MessageGenerator&) = delete;
+ MessageGenerator& operator=(const MessageGenerator&) = delete;
+
+ void GenerateStaticVariablesInitialization(io::Printer* printer);
+ void GenerateEnumHeader(io::Printer* printer);
+ void GenerateMessageHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+ void GenerateExtensionRegistrationSource(io::Printer* printer);
+ void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
+ void DetermineForwardDeclarations(std::set<std::string>* fwd_decls);
+
+ // Checks if the message or a nested message includes a oneof definition.
+ bool IncludesOneOfDefinition() const;
+
+ private:
+ void GenerateParseFromMethodsHeader(io::Printer* printer);
+
+ void GenerateSerializeOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRangeSource(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateMessageDescriptionSource(io::Printer* printer);
+ void GenerateDescriptionOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+
+ const std::string root_classname_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+ const std::string class_name_;
+ const std::string deprecated_attribute_;
+ std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+ std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
+ std::vector<std::unique_ptr<MessageGenerator>> nested_message_generators_;
+ std::vector<std::unique_ptr<OneofGenerator>> oneof_generators_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc
new file mode 100644
index 00000000..241ae0fa
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -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.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_message_field.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+#include <wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ const std::string& message_type = ClassName(descriptor->message_type());
+ const std::string& containing_class =
+ ClassName(descriptor->containing_type());
+ (*variables)["type"] = message_type;
+ (*variables)["containing_class"] = containing_class;
+ (*variables)["storage_type"] = message_type;
+ (*variables)["group_or_message"] =
+ (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
+ (*variables)["dataTypeSpecific_value"] = ObjCClass(message_type);
+}
+
+} // namespace
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
+ SetMessageVariables(descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const {
+ ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ // Class name is already in "storage_type".
+ fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+void MessageFieldGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const {
+ fwd_decls->insert(ObjCClassDeclaration(variable("storage_type")));
+}
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
+ SetMessageVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "NSMutableArray";
+ variables_["array_property_type"] =
+ "NSMutableArray<" + variables_["storage_type"] + "*>";
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const {
+ RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ // Class name is already in "storage_type".
+ fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const {
+ fwd_decls->insert(ObjCClassDeclaration(variable("storage_type")));
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h
new file mode 100644
index 00000000..7ea99c37
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -0,0 +1,87 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MessageFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ protected:
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+
+ MessageFieldGenerator(const MessageFieldGenerator&) = delete;
+ MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
+
+ virtual ~MessageFieldGenerator();
+
+ public:
+ virtual void DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const override;
+ virtual void DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const override;
+};
+
+class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ protected:
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual ~RepeatedMessageFieldGenerator();
+
+ RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
+ RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete;
+
+ public:
+ virtual void DetermineForwardDeclarations(
+ std::set<std::string>* fwd_decls) const override;
+ virtual void DetermineObjectiveCClassDefinitions(
+ std::set<std::string>* fwd_decls) const override;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
new file mode 100644
index 00000000..16330466
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
@@ -0,0 +1,197 @@
+// NSObject methods
+// Autogenerated by method_dump.sh. Do not edit by hand.
+// Date: Thu Nov 1 14:12:16 PDT 2018
+// macOS: MacOSX10.14.sdk
+// iOS: iPhoneSimulator12.1.sdk
+
+const char* const kNSObjectMethodsList[] = {
+ "CAMLType",
+ "CA_copyRenderValue",
+ "CA_prepareRenderValue",
+ "NS_copyCGImage",
+ "NS_tiledLayerVisibleRect",
+ "___tryRetain_OA",
+ "__autorelease_OA",
+ "__dealloc_zombie",
+ "__release_OA",
+ "__retain_OA",
+ "_accessibilityFinalize",
+ "_accessibilityIsTableViewDescendant",
+ "_accessibilityUIElementSpecifier",
+ "_accessibilityUseConvenienceAPI",
+ "_allowsDirectEncoding",
+ "_asScriptTerminologyNameArray",
+ "_asScriptTerminologyNameString",
+ "_bindingAdaptor",
+ "_cfTypeID",
+ "_copyDescription",
+ "_destroyObserverList",
+ "_didEndKeyValueObserving",
+ "_implicitObservationInfo",
+ "_internalAccessibilityAttributedHint",
+ "_internalAccessibilityAttributedLabel",
+ "_internalAccessibilityAttributedValue",
+ "_isAXConnector",
+ "_isAccessibilityContainerSectionCandidate",
+ "_isAccessibilityContentNavigatorSectionCandidate",
+ "_isAccessibilityContentSectionCandidate",
+ "_isAccessibilityTopLevelNavigatorSectionCandidate",
+ "_isDeallocating",
+ "_isKVOA",
+ "_isToManyChangeInformation",
+ "_ivarDescription",
+ "_localClassNameForClass",
+ "_methodDescription",
+ "_observerStorage",
+ "_overrideUseFastBlockObservers",
+ "_propertyDescription",
+ "_releaseBindingAdaptor",
+ "_scriptingCount",
+ "_scriptingCountNonrecursively",
+ "_scriptingDebugDescription",
+ "_scriptingExists",
+ "_scriptingShouldCheckObjectIndexes",
+ "_shortMethodDescription",
+ "_shouldSearchChildrenForSection",
+ "_traitStorageList",
+ "_tryRetain",
+ "_ui_descriptionBuilder",
+ "_uikit_variesByTraitCollections",
+ "_web_description",
+ "_webkit_invokeOnMainThread",
+ "_willBeginKeyValueObserving",
+ "accessibilityActivate",
+ "accessibilityActivationPoint",
+ "accessibilityAllowsOverriddenAttributesWhenIgnored",
+ "accessibilityAssistiveTechnologyFocusedIdentifiers",
+ "accessibilityAttributedHint",
+ "accessibilityAttributedLabel",
+ "accessibilityAttributedValue",
+ "accessibilityContainer",
+ "accessibilityContainerType",
+ "accessibilityCustomActions",
+ "accessibilityCustomRotors",
+ "accessibilityDecrement",
+ "accessibilityDragSourceDescriptors",
+ "accessibilityDropPointDescriptors",
+ "accessibilityElementCount",
+ "accessibilityElementDidBecomeFocused",
+ "accessibilityElementDidLoseFocus",
+ "accessibilityElementIsFocused",
+ "accessibilityElements",
+ "accessibilityElementsHidden",
+ "accessibilityFrame",
+ "accessibilityHeaderElements",
+ "accessibilityHint",
+ "accessibilityIdentification",
+ "accessibilityIdentifier",
+ "accessibilityIncrement",
+ "accessibilityLabel",
+ "accessibilityLanguage",
+ "accessibilityLocalizedStringKey",
+ "accessibilityNavigationStyle",
+ "accessibilityOverriddenAttributes",
+ "accessibilityParameterizedAttributeNames",
+ "accessibilityPath",
+ "accessibilityPerformEscape",
+ "accessibilityPerformMagicTap",
+ "accessibilityPresenterProcessIdentifier",
+ "accessibilityShouldUseUniqueId",
+ "accessibilitySupportsNotifications",
+ "accessibilitySupportsOverriddenAttributes",
+ "accessibilityTemporaryChildren",
+ "accessibilityTraits",
+ "accessibilityValue",
+ "accessibilityViewIsModal",
+ "accessibilityVisibleArea",
+ "allPropertyKeys",
+ "allowsWeakReference",
+ "attributeKeys",
+ "autoContentAccessingProxy",
+ "autorelease",
+ "awakeFromNib",
+ "boolValueSafe",
+ "bs_encoded",
+ "bs_isPlistableType",
+ "bs_secureEncoded",
+ "cl_json_serializeKey",
+ "class",
+ "classCode",
+ "classDescription",
+ "classForArchiver",
+ "classForCoder",
+ "classForKeyedArchiver",
+ "classForPortCoder",
+ "className",
+ "clearProperties",
+ "copy",
+ "dealloc",
+ "debugDescription",
+ "defaultAccessibilityTraits",
+ "description",
+ "doubleValueSafe",
+ "entityName",
+ "exposedBindings",
+ "finalize",
+ "finishObserving",
+ "flushKeyBindings",
+ "hash",
+ "init",
+ "int64ValueSafe",
+ "isAccessibilityElement",
+ "isAccessibilityElementByDefault",
+ "isElementAccessibilityExposedToInterfaceBuilder",
+ "isFault",
+ "isNSArray__",
+ "isNSCFConstantString__",
+ "isNSData__",
+ "isNSDate__",
+ "isNSDictionary__",
+ "isNSNumber__",
+ "isNSObject__",
+ "isNSOrderedSet__",
+ "isNSSet__",
+ "isNSString__",
+ "isNSTimeZone__",
+ "isNSValue__",
+ "isProxy",
+ "mutableCopy",
+ "nilValueForKey",
+ "objectSpecifier",
+ "observationInfo",
+ "pep_onDetachedThread",
+ "pep_onMainThread",
+ "pep_onMainThreadIfNecessary",
+ "prepareForInterfaceBuilder",
+ "release",
+ "releaseOnMainThread",
+ "retain",
+ "retainCount",
+ "retainWeakReference",
+ "scriptingProperties",
+ "self",
+ "shouldGroupAccessibilityChildren",
+ "storedAccessibilityActivationPoint",
+ "storedAccessibilityContainerType",
+ "storedAccessibilityElementsHidden",
+ "storedAccessibilityFrame",
+ "storedAccessibilityNavigationStyle",
+ "storedAccessibilityTraits",
+ "storedAccessibilityViewIsModal",
+ "storedIsAccessibilityElement",
+ "storedShouldGroupAccessibilityChildren",
+ "stringValueSafe",
+ "superclass",
+ "toManyRelationshipKeys",
+ "toOneRelationshipKeys",
+ "traitStorageList",
+ "un_safeBoolValue",
+ "userInterfaceItemIdentifier",
+ "utf8ValueSafe",
+ "valuesForKeysWithDictionary",
+ "zone",
+// Protocol: CAAnimatableValue
+// Protocol: CARenderValue
+// Protocol: NSObject
+// Protocol: ROCKRemoteInvocationInterface
+};
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc
new file mode 100644
index 00000000..de00a1f4
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -0,0 +1,140 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_oneof.h>
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
+ : descriptor_(descriptor) {
+ variables_["enum_name"] = OneofEnumName(descriptor_);
+ variables_["name"] = OneofName(descriptor_);
+ variables_["capitalized_name"] = OneofNameCapitalized(descriptor_);
+ variables_["raw_index"] = StrCat(descriptor_->index());
+ const Descriptor* msg_descriptor = descriptor_->containing_type();
+ variables_["owning_message_class"] = ClassName(msg_descriptor);
+
+ std::string comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ comments = BuildCommentsString(location, true);
+ } else {
+ comments = "";
+ }
+ variables_["comments"] = comments;
+}
+
+OneofGenerator::~OneofGenerator() {}
+
+void OneofGenerator::SetOneofIndexBase(int index_base) {
+ int index = descriptor_->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["index"] = StrCat(-index);
+}
+
+void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "typedef GPB_ENUM($enum_name$) {\n");
+ printer->Indent();
+ printer->Print(
+ variables_,
+ "$enum_name$_GPBUnsetOneOfCase = 0,\n");
+ std::string enum_name = variables_["enum_name"];
+ for (int j = 0; j < descriptor_->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->field(j);
+ std::string field_name = FieldNameCapitalized(field);
+ printer->Print(
+ "$enum_name$_$field_name$ = $field_number$,\n",
+ "enum_name", enum_name,
+ "field_name", field_name,
+ "field_number", StrCat(field->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+}
+
+void OneofGenerator::GeneratePublicCasePropertyDeclaration(
+ io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$comments$"
+ "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
+ "\n");
+}
+
+void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "/**\n"
+ " * Clears whatever value was set for the oneof '$name$'.\n"
+ " **/\n"
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
+}
+
+void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "@dynamic $name$OneOfCase;\n");
+}
+
+void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
+ " GPBClearOneof(message, oneof);\n"
+ "}\n");
+}
+
+std::string OneofGenerator::DescriptorName(void) const {
+ return variables_.find("name")->second;
+}
+
+std::string OneofGenerator::HasIndexAsString(void) const {
+ return variables_.find("index")->second;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h
new file mode 100644
index 00000000..3d59f4ff
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <descriptor.h>
+#include <io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class OneofGenerator {
+ public:
+ explicit OneofGenerator(const OneofDescriptor* descriptor);
+ ~OneofGenerator();
+
+ OneofGenerator(const OneofGenerator&) = delete;
+ OneofGenerator& operator=(const OneofGenerator&) = delete;
+
+ void SetOneofIndexBase(int index_base);
+
+ void GenerateCaseEnum(io::Printer* printer);
+
+ void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
+ void GenerateClearFunctionDeclaration(io::Printer* printer);
+
+ void GeneratePropertyImplementation(io::Printer* printer);
+ void GenerateClearFunctionImplementation(io::Printer* printer);
+
+ std::string DescriptorName(void) const;
+ std::string HasIndexAsString(void) const;
+
+ private:
+ const OneofDescriptor* descriptor_;
+ std::map<std::string, std::string> variables_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc
new file mode 100644
index 00000000..7b5eec0c
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -0,0 +1,190 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <map>
+#include <string>
+
+#include <compiler/objectivec/objectivec_helpers.h>
+#include <compiler/objectivec/objectivec_primitive_field.h>
+#include <io/printer.h>
+#include <stubs/strutil.h>
+#include <wire_format.h>
+#include <wire_format_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "int32_t";
+ case OBJECTIVECTYPE_UINT32:
+ return "uint32_t";
+ case OBJECTIVECTYPE_INT64:
+ return "int64_t";
+ case OBJECTIVECTYPE_UINT64:
+ return "uint64_t";
+ case OBJECTIVECTYPE_FLOAT:
+ return "float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "BOOL";
+ case OBJECTIVECTYPE_STRING:
+ return "NSString";
+ case OBJECTIVECTYPE_DATA:
+ return "NSData";
+ case OBJECTIVECTYPE_ENUM:
+ return "int32_t";
+ case OBJECTIVECTYPE_MESSAGE:
+ return NULL; // Messages go through objectivec_message_field.cc|h.
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_DATA:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ // Want NSArray (but goes through objectivec_message_field.cc|h).
+ return "";
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ std::map<std::string, std::string>* variables) {
+ std::string primitive_name = PrimitiveTypeName(descriptor);
+ (*variables)["type"] = primitive_name;
+ (*variables)["storage_type"] = primitive_name;
+}
+
+} // namespace
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
+ SetPrimitiveVariables(descriptor, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+ // Nothing, BOOLs are stored in the has bits.
+ } else {
+ SingleFieldGenerator::GenerateFieldStorageDeclaration(printer);
+ }
+}
+
+int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+ if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+ // Reserve a bit for the storage of the boolean.
+ return 1;
+ }
+ return 0;
+}
+
+void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
+ if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+ // Set into the offset the has bit to use for the actual value.
+ variables_["storage_offset_value"] = StrCat(has_base);
+ variables_["storage_offset_comment"] =
+ " // Stored in _has_storage_ to save space.";
+ }
+}
+
+PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
+ SetPrimitiveVariables(descriptor, &variables_);
+ variables_["property_storage_attribute"] = "copy";
+}
+
+PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
+ SetPrimitiveVariables(descriptor, &variables_);
+
+ std::string base_name = PrimitiveArrayTypeName(descriptor);
+ if (base_name.length()) {
+ variables_["array_storage_type"] = "GPB" + base_name + "Array";
+ } else {
+ variables_["array_storage_type"] = "NSMutableArray";
+ variables_["array_property_type"] =
+ "NSMutableArray<" + variables_["storage_type"] + "*>";
+ }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h
new file mode 100644
index 00000000..88e91ba8
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class PrimitiveFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ protected:
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual ~PrimitiveFieldGenerator();
+
+ PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
+ PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+
+ virtual int ExtraRuntimeHasBitsNeeded(void) const override;
+ virtual void SetExtraRuntimeHasBitsBase(int index_base) override;
+};
+
+class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ protected:
+ PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual ~PrimitiveObjFieldGenerator();
+
+ PrimitiveObjFieldGenerator(const PrimitiveObjFieldGenerator&) = delete;
+ PrimitiveObjFieldGenerator& operator=(const PrimitiveObjFieldGenerator&) =
+ delete;
+};
+
+class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
+
+ protected:
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
+ virtual ~RepeatedPrimitiveFieldGenerator();
+
+ RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) =
+ delete;
+ RepeatedPrimitiveFieldGenerator& operator=(
+ const RepeatedPrimitiveFieldGenerator&) = delete;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/package_info.h b/NorthstarDedicatedTest/include/protobuf/compiler/package_info.h
new file mode 100644
index 00000000..105ef601
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/package_info.h
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file exists solely to document the google::protobuf::compiler namespace.
+// It is not compiled into anything, but it may be read by an automated
+// documentation generator.
+
+namespace google {
+namespace protobuf {
+
+// Implementation of the Protocol Buffer compiler.
+//
+// This package contains code for parsing .proto files and generating code
+// based on them. There are two reasons you might be interested in this
+// package:
+// - You want to parse .proto files at runtime. In this case, you should
+// look at importer.h. Since this functionality is widely useful, it is
+// included in the libprotobuf base library; you do not have to link against
+// libprotoc.
+// - You want to write a custom protocol compiler which generates different
+// kinds of code, e.g. code in a different language which is not supported
+// by the official compiler. For this purpose, command_line_interface.h
+// provides you with a complete compiler front-end, so all you need to do
+// is write a custom implementation of CodeGenerator and a trivial main()
+// function. You can even make your compiler support the official languages
+// in addition to your own. Since this functionality is only useful to those
+// writing custom compilers, it is in a separate library called "libprotoc"
+// which you will have to link against.
+namespace compiler {}
+
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/parser.cc b/NorthstarDedicatedTest/include/protobuf/compiler/parser.cc
new file mode 100644
index 00000000..6d84ac9f
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/parser.cc
@@ -0,0 +1,2445 @@
+// 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.
+//
+// Recursive descent FTW.
+
+#include <compiler/parser.h>
+
+#include <float.h>
+
+#include <cstdint>
+#include <limits>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <stubs/casts.h>
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <descriptor.pb.h>
+#include <io/tokenizer.h>
+#include <descriptor.h>
+#include <wire_format.h>
+#include <stubs/strutil.h>
+#include <stubs/map_util.h>
+#include <stubs/hash.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+using internal::WireFormat;
+
+namespace {
+
+typedef std::unordered_map<std::string, FieldDescriptorProto::Type> TypeNameMap;
+
+TypeNameMap MakeTypeNameTable() {
+ TypeNameMap result;
+
+ result["double"] = FieldDescriptorProto::TYPE_DOUBLE;
+ result["float"] = FieldDescriptorProto::TYPE_FLOAT;
+ result["uint64"] = FieldDescriptorProto::TYPE_UINT64;
+ result["fixed64"] = FieldDescriptorProto::TYPE_FIXED64;
+ result["fixed32"] = FieldDescriptorProto::TYPE_FIXED32;
+ result["bool"] = FieldDescriptorProto::TYPE_BOOL;
+ result["string"] = FieldDescriptorProto::TYPE_STRING;
+ result["group"] = FieldDescriptorProto::TYPE_GROUP;
+
+ result["bytes"] = FieldDescriptorProto::TYPE_BYTES;
+ result["uint32"] = FieldDescriptorProto::TYPE_UINT32;
+ result["sfixed32"] = FieldDescriptorProto::TYPE_SFIXED32;
+ result["sfixed64"] = FieldDescriptorProto::TYPE_SFIXED64;
+ result["int32"] = FieldDescriptorProto::TYPE_INT32;
+ result["int64"] = FieldDescriptorProto::TYPE_INT64;
+ result["sint32"] = FieldDescriptorProto::TYPE_SINT32;
+ result["sint64"] = FieldDescriptorProto::TYPE_SINT64;
+
+ return result;
+}
+
+const TypeNameMap kTypeNames = MakeTypeNameTable();
+
+// Camel-case the field name and append "Entry" for generated map entry name.
+// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
+std::string MapEntryName(const std::string& field_name) {
+ std::string result;
+ static const char kSuffix[] = "Entry";
+ result.reserve(field_name.size() + sizeof(kSuffix));
+ bool cap_next = true;
+ for (const char field_name_char : field_name) {
+ if (field_name_char == '_') {
+ cap_next = true;
+ } else if (cap_next) {
+ // Note: Do not use ctype.h due to locales.
+ if ('a' <= field_name_char && field_name_char <= 'z') {
+ result.push_back(field_name_char - 'a' + 'A');
+ } else {
+ result.push_back(field_name_char);
+ }
+ cap_next = false;
+ } else {
+ result.push_back(field_name_char);
+ }
+ }
+ result.append(kSuffix);
+ return result;
+}
+
+bool IsUppercase(char c) { return c >= 'A' && c <= 'Z'; }
+
+bool IsLowercase(char c) { return c >= 'a' && c <= 'z'; }
+
+bool IsNumber(char c) { return c >= '0' && c <= '9'; }
+
+bool IsUpperCamelCase(const std::string& name) {
+ if (name.empty()) {
+ return true;
+ }
+ // Name must start with an upper case character.
+ if (!IsUppercase(name[0])) {
+ return false;
+ }
+ // Must not contains underscore.
+ for (const char c : name) {
+ if (c == '_') {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsUpperUnderscore(const std::string& name) {
+ for (const char c : name) {
+ if (!IsUppercase(c) && c != '_' && !IsNumber(c)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsLowerUnderscore(const std::string& name) {
+ for (const char c : name) {
+ if (!IsLowercase(c) && c != '_' && !IsNumber(c)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsNumberFollowUnderscore(const std::string& name) {
+ for (int i = 1; i < name.length(); i++) {
+ const char c = name[i];
+ if (IsNumber(c) && name[i - 1] == '_') {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // anonymous namespace
+
+// Makes code slightly more readable. The meaning of "DO(foo)" is
+// "Execute foo and fail if it fails.", where failure is indicated by
+// returning false.
+#define DO(STATEMENT) \
+ if (STATEMENT) { \
+ } else \
+ return false
+
+// ===================================================================
+
+Parser::Parser()
+ : input_(NULL),
+ error_collector_(NULL),
+ source_location_table_(NULL),
+ had_errors_(false),
+ require_syntax_identifier_(false),
+ stop_after_syntax_identifier_(false) {
+}
+
+Parser::~Parser() {}
+
+// ===================================================================
+
+inline bool Parser::LookingAt(const char* text) {
+ return input_->current().text == text;
+}
+
+inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) {
+ return input_->current().type == token_type;
+}
+
+inline bool Parser::AtEnd() { return LookingAtType(io::Tokenizer::TYPE_END); }
+
+bool Parser::TryConsume(const char* text) {
+ if (LookingAt(text)) {
+ input_->Next();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Parser::Consume(const char* text, const char* error) {
+ if (TryConsume(text)) {
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::Consume(const char* text) {
+ if (TryConsume(text)) {
+ return true;
+ } else {
+ AddError("Expected \"" + std::string(text) + "\".");
+ return false;
+ }
+}
+
+bool Parser::ConsumeIdentifier(std::string* output, const char* error) {
+ if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+ *output = input_->current().text;
+ input_->Next();
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::ConsumeInteger(int* output, const char* error) {
+ if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+ uint64_t value = 0;
+ if (!io::Tokenizer::ParseInteger(input_->current().text,
+ std::numeric_limits<int32_t>::max(),
+ &value)) {
+ AddError("Integer out of range.");
+ // We still return true because we did, in fact, parse an integer.
+ }
+ *output = value;
+ input_->Next();
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::ConsumeSignedInteger(int* output, const char* error) {
+ bool is_negative = false;
+ uint64_t max_value = std::numeric_limits<int32_t>::max();
+ if (TryConsume("-")) {
+ is_negative = true;
+ max_value += 1;
+ }
+ uint64_t value = 0;
+ DO(ConsumeInteger64(max_value, &value, error));
+ if (is_negative) value *= -1;
+ *output = value;
+ return true;
+}
+
+bool Parser::ConsumeInteger64(uint64_t max_value, uint64_t* output,
+ const char* error) {
+ if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+ if (!io::Tokenizer::ParseInteger(input_->current().text, max_value,
+ output)) {
+ AddError("Integer out of range.");
+ // We still return true because we did, in fact, parse an integer.
+ *output = 0;
+ }
+ input_->Next();
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::ConsumeNumber(double* output, const char* error) {
+ if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
+ *output = io::Tokenizer::ParseFloat(input_->current().text);
+ input_->Next();
+ return true;
+ } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+ // Also accept integers.
+ uint64_t value = 0;
+ if (!io::Tokenizer::ParseInteger(input_->current().text,
+ std::numeric_limits<uint64_t>::max(),
+ &value)) {
+ AddError("Integer out of range.");
+ // We still return true because we did, in fact, parse a number.
+ }
+ *output = value;
+ input_->Next();
+ return true;
+ } else if (LookingAt("inf")) {
+ *output = std::numeric_limits<double>::infinity();
+ input_->Next();
+ return true;
+ } else if (LookingAt("nan")) {
+ *output = std::numeric_limits<double>::quiet_NaN();
+ input_->Next();
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::ConsumeString(std::string* output, const char* error) {
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ io::Tokenizer::ParseString(input_->current().text, output);
+ input_->Next();
+ // Allow C++ like concatenation of adjacent string tokens.
+ while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ io::Tokenizer::ParseStringAppend(input_->current().text, output);
+ input_->Next();
+ }
+ return true;
+ } else {
+ AddError(error);
+ return false;
+ }
+}
+
+bool Parser::TryConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location) {
+ if (LookingAt(text)) {
+ std::string leading, trailing;
+ std::vector<std::string> detached;
+ input_->NextWithComments(&trailing, &detached, &leading);
+
+ // Save the leading comments for next time, and recall the leading comments
+ // from last time.
+ leading.swap(upcoming_doc_comments_);
+
+ if (location != NULL) {
+ upcoming_detached_comments_.swap(detached);
+ location->AttachComments(&leading, &trailing, &detached);
+ } else if (strcmp(text, "}") == 0) {
+ // If the current location is null and we are finishing the current scope,
+ // drop pending upcoming detached comments.
+ upcoming_detached_comments_.swap(detached);
+ } else {
+ // Otherwise, append the new detached comments to the existing upcoming
+ // detached comments.
+ upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
+ detached.begin(), detached.end());
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Parser::ConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location) {
+ if (TryConsumeEndOfDeclaration(text, location)) {
+ return true;
+ } else {
+ AddError("Expected \"" + std::string(text) + "\".");
+ return false;
+ }
+}
+
+// -------------------------------------------------------------------
+
+void Parser::AddError(int line, int column, const std::string& error) {
+ if (error_collector_ != NULL) {
+ error_collector_->AddError(line, column, error);
+ }
+ had_errors_ = true;
+}
+
+void Parser::AddError(const std::string& error) {
+ AddError(input_->current().line, input_->current().column, error);
+}
+
+void Parser::AddWarning(const std::string& warning) {
+ if (error_collector_ != nullptr) {
+ error_collector_->AddWarning(input_->current().line,
+ input_->current().column, warning);
+ }
+}
+
+// -------------------------------------------------------------------
+
+Parser::LocationRecorder::LocationRecorder(Parser* parser)
+ : parser_(parser),
+ source_code_info_(parser->source_code_info_),
+ location_(parser_->source_code_info_->add_location()) {
+ location_->add_span(parser_->input_->current().line);
+ location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) {
+ Init(parent, parent.source_code_info_);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+ int path1,
+ SourceCodeInfo* source_code_info) {
+ Init(parent, source_code_info);
+ AddPath(path1);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+ int path1) {
+ Init(parent, parent.source_code_info_);
+ AddPath(path1);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+ int path1, int path2) {
+ Init(parent, parent.source_code_info_);
+ AddPath(path1);
+ AddPath(path2);
+}
+
+void Parser::LocationRecorder::Init(const LocationRecorder& parent,
+ SourceCodeInfo* source_code_info) {
+ parser_ = parent.parser_;
+ source_code_info_ = source_code_info;
+
+ location_ = source_code_info_->add_location();
+ location_->mutable_path()->CopyFrom(parent.location_->path());
+
+ location_->add_span(parser_->input_->current().line);
+ location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::~LocationRecorder() {
+ if (location_->span_size() <= 2) {
+ EndAt(parser_->input_->previous());
+ }
+}
+
+void Parser::LocationRecorder::AddPath(int path_component) {
+ location_->add_path(path_component);
+}
+
+void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
+ location_->set_span(0, token.line);
+ location_->set_span(1, token.column);
+}
+
+void Parser::LocationRecorder::StartAt(const LocationRecorder& other) {
+ location_->set_span(0, other.location_->span(0));
+ location_->set_span(1, other.location_->span(1));
+}
+
+void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) {
+ if (token.line != location_->span(0)) {
+ location_->add_span(token.line);
+ }
+ location_->add_span(token.end_column);
+}
+
+void Parser::LocationRecorder::RecordLegacyLocation(
+ const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location) {
+ if (parser_->source_location_table_ != NULL) {
+ parser_->source_location_table_->Add(
+ descriptor, location, location_->span(0), location_->span(1));
+ }
+}
+
+void Parser::LocationRecorder::RecordLegacyImportLocation(
+ const Message* descriptor, const std::string& name) {
+ if (parser_->source_location_table_ != nullptr) {
+ parser_->source_location_table_->AddImport(
+ descriptor, name, location_->span(0), location_->span(1));
+ }
+}
+
+int Parser::LocationRecorder::CurrentPathSize() const {
+ return location_->path_size();
+}
+
+void Parser::LocationRecorder::AttachComments(
+ std::string* leading, std::string* trailing,
+ std::vector<std::string>* detached_comments) const {
+ GOOGLE_CHECK(!location_->has_leading_comments());
+ GOOGLE_CHECK(!location_->has_trailing_comments());
+
+ if (!leading->empty()) {
+ location_->mutable_leading_comments()->swap(*leading);
+ }
+ if (!trailing->empty()) {
+ location_->mutable_trailing_comments()->swap(*trailing);
+ }
+ for (int i = 0; i < detached_comments->size(); ++i) {
+ location_->add_leading_detached_comments()->swap((*detached_comments)[i]);
+ }
+ detached_comments->clear();
+}
+
+// -------------------------------------------------------------------
+
+void Parser::SkipStatement() {
+ while (true) {
+ if (AtEnd()) {
+ return;
+ } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ return;
+ } else if (TryConsume("{")) {
+ SkipRestOfBlock();
+ return;
+ } else if (LookingAt("}")) {
+ return;
+ }
+ }
+ input_->Next();
+ }
+}
+
+void Parser::SkipRestOfBlock() {
+ while (true) {
+ if (AtEnd()) {
+ return;
+ } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
+ if (TryConsumeEndOfDeclaration("}", NULL)) {
+ return;
+ } else if (TryConsume("{")) {
+ SkipRestOfBlock();
+ }
+ }
+ input_->Next();
+ }
+}
+
+// ===================================================================
+
+bool Parser::ValidateEnum(const EnumDescriptorProto* proto) {
+ bool has_allow_alias = false;
+ bool allow_alias = false;
+
+ for (int i = 0; i < proto->options().uninterpreted_option_size(); i++) {
+ const UninterpretedOption option = proto->options().uninterpreted_option(i);
+ if (option.name_size() > 1) {
+ continue;
+ }
+ if (!option.name(0).is_extension() &&
+ option.name(0).name_part() == "allow_alias") {
+ has_allow_alias = true;
+ if (option.identifier_value() == "true") {
+ allow_alias = true;
+ }
+ break;
+ }
+ }
+
+ if (has_allow_alias && !allow_alias) {
+ std::string error =
+ "\"" + proto->name() +
+ "\" declares 'option allow_alias = false;' which has no effect. "
+ "Please remove the declaration.";
+ // This needlessly clutters declarations with nops.
+ AddError(error);
+ return false;
+ }
+
+ std::set<int> used_values;
+ bool has_duplicates = false;
+ for (int i = 0; i < proto->value_size(); ++i) {
+ const EnumValueDescriptorProto& enum_value = proto->value(i);
+ if (used_values.find(enum_value.number()) != used_values.end()) {
+ has_duplicates = true;
+ break;
+ } else {
+ used_values.insert(enum_value.number());
+ }
+ }
+ if (allow_alias && !has_duplicates) {
+ std::string error =
+ "\"" + proto->name() +
+ "\" declares support for enum aliases but no enum values share field "
+ "numbers. Please remove the unnecessary 'option allow_alias = true;' "
+ "declaration.";
+ // Generate an error if an enum declares support for duplicate enum values
+ // and does not use it protect future authors.
+ AddError(error);
+ return false;
+ }
+
+ // Enforce that enum constants must be UPPER_CASE except in case of
+ // enum_alias.
+ if (!allow_alias) {
+ for (const auto& enum_value : proto->value()) {
+ if (!IsUpperUnderscore(enum_value.name())) {
+ AddWarning(
+ "Enum constant should be in UPPER_CASE. Found: " +
+ enum_value.name() +
+ ". See https://developers.google.com/protocol-buffers/docs/style");
+ }
+ }
+ }
+
+ return true;
+}
+
+bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
+ input_ = input;
+ had_errors_ = false;
+ syntax_identifier_.clear();
+
+ // Note that |file| could be NULL at this point if
+ // stop_after_syntax_identifier_ is true. So, we conservatively allocate
+ // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto
+ // later on.
+ SourceCodeInfo source_code_info;
+ source_code_info_ = &source_code_info;
+
+ if (LookingAtType(io::Tokenizer::TYPE_START)) {
+ // Advance to first token.
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
+ }
+
+ {
+ LocationRecorder root_location(this);
+ root_location.RecordLegacyLocation(file,
+ DescriptorPool::ErrorCollector::OTHER);
+
+ if (require_syntax_identifier_ || LookingAt("syntax")) {
+ if (!ParseSyntaxIdentifier(root_location)) {
+ // Don't attempt to parse the file if we didn't recognize the syntax
+ // identifier.
+ return false;
+ }
+ // Store the syntax into the file.
+ if (file != NULL) file->set_syntax(syntax_identifier_);
+ } else if (!stop_after_syntax_identifier_) {
+ GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: " << file->name()
+ << ". Please use 'syntax = \"proto2\";' "
+ << "or 'syntax = \"proto3\";' to specify a syntax "
+ << "version. (Defaulted to proto2 syntax.)";
+ syntax_identifier_ = "proto2";
+ }
+
+ if (stop_after_syntax_identifier_) return !had_errors_;
+
+ // Repeatedly parse statements until we reach the end of the file.
+ while (!AtEnd()) {
+ if (!ParseTopLevelStatement(file, root_location)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+
+ if (LookingAt("}")) {
+ AddError("Unmatched \"}\".");
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
+ }
+ }
+ }
+ }
+
+ input_ = NULL;
+ source_code_info_ = NULL;
+ assert(file != NULL);
+ source_code_info.Swap(file->mutable_source_code_info());
+ return !had_errors_;
+}
+
+bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
+ LocationRecorder syntax_location(parent,
+ FileDescriptorProto::kSyntaxFieldNumber);
+ DO(Consume(
+ "syntax",
+ "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
+ DO(Consume("="));
+ io::Tokenizer::Token syntax_token = input_->current();
+ std::string syntax;
+ DO(ConsumeString(&syntax, "Expected syntax identifier."));
+ DO(ConsumeEndOfDeclaration(";", &syntax_location));
+
+ syntax_identifier_ = syntax;
+
+ if (syntax != "proto2" && syntax != "proto3" &&
+ !stop_after_syntax_identifier_) {
+ AddError(syntax_token.line, syntax_token.column,
+ "Unrecognized syntax identifier \"" + syntax +
+ "\". This parser "
+ "only recognizes \"proto2\" and \"proto3\".");
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
+ const LocationRecorder& root_location) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ return true;
+ } else if (LookingAt("message")) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kMessageTypeFieldNumber,
+ file->message_type_size());
+ return ParseMessageDefinition(file->add_message_type(), location, file);
+ } else if (LookingAt("enum")) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kEnumTypeFieldNumber,
+ file->enum_type_size());
+ return ParseEnumDefinition(file->add_enum_type(), location, file);
+ } else if (LookingAt("service")) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kServiceFieldNumber,
+ file->service_size());
+ return ParseServiceDefinition(file->add_service(), location, file);
+ } else if (LookingAt("extend")) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kExtensionFieldNumber);
+ return ParseExtend(
+ file->mutable_extension(), file->mutable_message_type(), root_location,
+ FileDescriptorProto::kMessageTypeFieldNumber, location, file);
+ } else if (LookingAt("import")) {
+ return ParseImport(file->mutable_dependency(),
+ file->mutable_public_dependency(),
+ file->mutable_weak_dependency(), root_location, file);
+ } else if (LookingAt("package")) {
+ return ParsePackage(file, root_location, file);
+ } else if (LookingAt("option")) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kOptionsFieldNumber);
+ return ParseOption(file->mutable_options(), location, file,
+ OPTION_STATEMENT);
+ } else {
+ AddError("Expected top-level statement (e.g. \"message\").");
+ return false;
+ }
+}
+
+// -------------------------------------------------------------------
+// Messages
+
+bool Parser::ParseMessageDefinition(
+ DescriptorProto* message, const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("message"));
+ {
+ LocationRecorder location(message_location,
+ DescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(message,
+ DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
+ if (!IsUpperCamelCase(message->name())) {
+ AddWarning(
+ "Message name should be in UpperCamelCase. Found: " +
+ message->name() +
+ ". See https://developers.google.com/protocol-buffers/docs/style");
+ }
+ }
+ DO(ParseMessageBlock(message, message_location, containing_file));
+
+ if (syntax_identifier_ == "proto3") {
+ // Add synthetic one-field oneofs for optional fields, except messages which
+ // already have presence in proto3.
+ //
+ // We have to make sure the oneof names don't conflict with any other
+ // field or oneof.
+ std::unordered_set<std::string> names;
+ for (const auto& field : message->field()) {
+ names.insert(field.name());
+ }
+ for (const auto& oneof : message->oneof_decl()) {
+ names.insert(oneof.name());
+ }
+
+ for (auto& field : *message->mutable_field()) {
+ if (field.proto3_optional()) {
+ std::string oneof_name = field.name();
+
+ // Prepend 'XXXXX_' until we are no longer conflicting.
+ // Avoid prepending a double-underscore because such names are
+ // reserved in C++.
+ if (oneof_name.empty() || oneof_name[0] != '_') {
+ oneof_name = '_' + oneof_name;
+ }
+ while (names.count(oneof_name) > 0) {
+ oneof_name = 'X' + oneof_name;
+ }
+
+ names.insert(oneof_name);
+ field.set_oneof_index(message->oneof_decl_size());
+ OneofDescriptorProto* oneof = message->add_oneof_decl();
+ oneof->set_name(oneof_name);
+ }
+ }
+ }
+
+ return true;
+}
+
+namespace {
+
+const int kMaxRangeSentinel = -1;
+
+bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
+ const MessageOptions& options = message.options();
+ for (int i = 0; i < options.uninterpreted_option_size(); ++i) {
+ const UninterpretedOption& uninterpreted = options.uninterpreted_option(i);
+ if (uninterpreted.name_size() == 1 &&
+ uninterpreted.name(0).name_part() == "message_set_wire_format" &&
+ uninterpreted.identifier_value() == "true") {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Modifies any extension ranges that specified 'max' as the end of the
+// extension range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
+ const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+ const int max_extension_number = is_message_set
+ ? std::numeric_limits<int32_t>::max()
+ : FieldDescriptor::kMaxNumber + 1;
+ for (int i = 0; i < message->extension_range_size(); ++i) {
+ if (message->extension_range(i).end() == kMaxRangeSentinel) {
+ message->mutable_extension_range(i)->set_end(max_extension_number);
+ }
+ }
+}
+
+// Modifies any reserved ranges that specified 'max' as the end of the
+// reserved range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
+ const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+ const int max_field_number = is_message_set
+ ? std::numeric_limits<int32_t>::max()
+ : FieldDescriptor::kMaxNumber + 1;
+ for (int i = 0; i < message->reserved_range_size(); ++i) {
+ if (message->reserved_range(i).end() == kMaxRangeSentinel) {
+ message->mutable_reserved_range(i)->set_end(max_field_number);
+ }
+ }
+}
+
+} // namespace
+
+bool Parser::ParseMessageBlock(DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
+ DO(ConsumeEndOfDeclaration("{", &message_location));
+
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
+ if (AtEnd()) {
+ AddError("Reached end of input in message definition (missing '}').");
+ return false;
+ }
+
+ if (!ParseMessageStatement(message, message_location, containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ }
+
+ if (message->extension_range_size() > 0) {
+ AdjustExtensionRangesWithMaxEndNumber(message);
+ }
+ if (message->reserved_range_size() > 0) {
+ AdjustReservedRangesWithMaxEndNumber(message);
+ }
+ return true;
+}
+
+bool Parser::ParseMessageStatement(DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ return true;
+ } else if (LookingAt("message")) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kNestedTypeFieldNumber,
+ message->nested_type_size());
+ return ParseMessageDefinition(message->add_nested_type(), location,
+ containing_file);
+ } else if (LookingAt("enum")) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kEnumTypeFieldNumber,
+ message->enum_type_size());
+ return ParseEnumDefinition(message->add_enum_type(), location,
+ containing_file);
+ } else if (LookingAt("extensions")) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kExtensionRangeFieldNumber);
+ return ParseExtensions(message, location, containing_file);
+ } else if (LookingAt("reserved")) {
+ return ParseReserved(message, message_location);
+ } else if (LookingAt("extend")) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kExtensionFieldNumber);
+ return ParseExtend(message->mutable_extension(),
+ message->mutable_nested_type(), message_location,
+ DescriptorProto::kNestedTypeFieldNumber, location,
+ containing_file);
+ } else if (LookingAt("option")) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kOptionsFieldNumber);
+ return ParseOption(message->mutable_options(), location, containing_file,
+ OPTION_STATEMENT);
+ } else if (LookingAt("oneof")) {
+ int oneof_index = message->oneof_decl_size();
+ LocationRecorder oneof_location(
+ message_location, DescriptorProto::kOneofDeclFieldNumber, oneof_index);
+
+ return ParseOneof(message->add_oneof_decl(), message, oneof_index,
+ oneof_location, message_location, containing_file);
+ } else {
+ LocationRecorder location(message_location,
+ DescriptorProto::kFieldFieldNumber,
+ message->field_size());
+ return ParseMessageField(
+ message->add_field(), message->mutable_nested_type(), message_location,
+ DescriptorProto::kNestedTypeFieldNumber, location, containing_file);
+ }
+}
+
+bool Parser::ParseMessageField(FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ {
+ FieldDescriptorProto::Label label;
+ if (ParseLabel(&label, field_location, containing_file)) {
+ field->set_label(label);
+ if (label == FieldDescriptorProto::LABEL_OPTIONAL &&
+ syntax_identifier_ == "proto3") {
+ field->set_proto3_optional(true);
+ }
+ }
+ }
+
+ return ParseMessageFieldNoLabel(field, messages, parent_location,
+ location_field_number_for_nested_type,
+ field_location, containing_file);
+}
+
+bool Parser::ParseMessageFieldNoLabel(
+ FieldDescriptorProto* field, RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ MapField map_field;
+ // Parse type.
+ {
+ LocationRecorder location(field_location); // add path later
+ location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+
+ bool type_parsed = false;
+ FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
+ std::string type_name;
+
+ // Special case map field. We only treat the field as a map field if the
+ // field type name starts with the word "map" with a following "<".
+ if (TryConsume("map")) {
+ if (LookingAt("<")) {
+ map_field.is_map_field = true;
+ } else {
+ // False positive
+ type_parsed = true;
+ type_name = "map";
+ }
+ }
+ if (map_field.is_map_field) {
+ if (field->has_oneof_index()) {
+ AddError("Map fields are not allowed in oneofs.");
+ return false;
+ }
+ if (field->has_label()) {
+ AddError(
+ "Field labels (required/optional/repeated) are not allowed on "
+ "map fields.");
+ return false;
+ }
+ if (field->has_extendee()) {
+ AddError("Map fields are not allowed to be extensions.");
+ return false;
+ }
+ field->set_label(FieldDescriptorProto::LABEL_REPEATED);
+ DO(Consume("<"));
+ DO(ParseType(&map_field.key_type, &map_field.key_type_name));
+ DO(Consume(","));
+ DO(ParseType(&map_field.value_type, &map_field.value_type_name));
+ DO(Consume(">"));
+ // Defer setting of the type name of the map field until the
+ // field name is parsed. Add the source location though.
+ location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+ } else {
+ // Handle the case where no explicit label is given for a non-map field.
+ if (!field->has_label() && DefaultToOptionalFields()) {
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+ if (!field->has_label()) {
+ AddError("Expected \"required\", \"optional\", or \"repeated\".");
+ // We can actually reasonably recover here by just assuming the user
+ // forgot the label altogether.
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+
+ // Handle the case where the actual type is a message or enum named "map",
+ // which we already consumed in the code above.
+ if (!type_parsed) {
+ DO(ParseType(&type, &type_name));
+ }
+ if (type_name.empty()) {
+ location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+ field->set_type(type);
+ } else {
+ location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+ field->set_type_name(type_name);
+ }
+ }
+ }
+
+ // Parse name and '='.
+ io::Tokenizer::Token name_token = input_->current();
+ {
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+
+ if (!IsLowerUnderscore(field->name())) {
+ AddWarning(
+ "Field name should be lowercase. Found: " + field->name() +
+ ". See: https://developers.google.com/protocol-buffers/docs/style");
+ }
+ if (IsNumberFollowUnderscore(field->name())) {
+ AddWarning(
+ "Number should not come right after an underscore. Found: " +
+ field->name() +
+ ". See: https://developers.google.com/protocol-buffers/docs/style");
+ }
+ }
+ DO(Consume("=", "Missing field number."));
+
+ // Parse field number.
+ {
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kNumberFieldNumber);
+ location.RecordLegacyLocation(field,
+ DescriptorPool::ErrorCollector::NUMBER);
+ int number;
+ DO(ConsumeInteger(&number, "Expected field number."));
+ field->set_number(number);
+ }
+
+ // Parse options.
+ DO(ParseFieldOptions(field, field_location, containing_file));
+
+ // Deal with groups.
+ if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) {
+ // Awkward: Since a group declares both a message type and a field, we
+ // have to create overlapping locations.
+ LocationRecorder group_location(parent_location);
+ group_location.StartAt(field_location);
+ group_location.AddPath(location_field_number_for_nested_type);
+ group_location.AddPath(messages->size());
+
+ DescriptorProto* group = messages->Add();
+ group->set_name(field->name());
+
+ // Record name location to match the field name's location.
+ {
+ LocationRecorder location(group_location,
+ DescriptorProto::kNameFieldNumber);
+ location.StartAt(name_token);
+ location.EndAt(name_token);
+ location.RecordLegacyLocation(group,
+ DescriptorPool::ErrorCollector::NAME);
+ }
+
+ // The field's type_name also comes from the name. Confusing!
+ {
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kTypeNameFieldNumber);
+ location.StartAt(name_token);
+ location.EndAt(name_token);
+ }
+
+ // As a hack for backwards-compatibility, we force the group name to start
+ // with a capital letter and lower-case the field name. New code should
+ // not use groups; it should use nested messages.
+ if (group->name()[0] < 'A' || 'Z' < group->name()[0]) {
+ AddError(name_token.line, name_token.column,
+ "Group names must start with a capital letter.");
+ }
+ LowerString(field->mutable_name());
+
+ field->set_type_name(group->name());
+ if (LookingAt("{")) {
+ DO(ParseMessageBlock(group, group_location, containing_file));
+ } else {
+ AddError("Missing group body.");
+ return false;
+ }
+ } else {
+ DO(ConsumeEndOfDeclaration(";", &field_location));
+ }
+
+ // Create a map entry type if this is a map field.
+ if (map_field.is_map_field) {
+ GenerateMapEntry(map_field, field, messages);
+ }
+
+ return true;
+}
+
+void Parser::GenerateMapEntry(const MapField& map_field,
+ FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages) {
+ DescriptorProto* entry = messages->Add();
+ std::string entry_name = MapEntryName(field->name());
+ field->set_type_name(entry_name);
+ entry->set_name(entry_name);
+ entry->mutable_options()->set_map_entry(true);
+ FieldDescriptorProto* key_field = entry->add_field();
+ key_field->set_name("key");
+ key_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ key_field->set_number(1);
+ if (map_field.key_type_name.empty()) {
+ key_field->set_type(map_field.key_type);
+ } else {
+ key_field->set_type_name(map_field.key_type_name);
+ }
+ FieldDescriptorProto* value_field = entry->add_field();
+ value_field->set_name("value");
+ value_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ value_field->set_number(2);
+ if (map_field.value_type_name.empty()) {
+ value_field->set_type(map_field.value_type);
+ } else {
+ value_field->set_type_name(map_field.value_type_name);
+ }
+ // Propagate the "enforce_utf8" option to key and value fields if they
+ // are strings. This helps simplify the implementation of code generators
+ // and also reflection-based parsing code.
+ //
+ // The following definition:
+ // message Foo {
+ // map<string, string> value = 1 [enforce_utf8 = false];
+ // }
+ // will be interpreted as:
+ // message Foo {
+ // message ValueEntry {
+ // option map_entry = true;
+ // string key = 1 [enforce_utf8 = false];
+ // string value = 2 [enforce_utf8 = false];
+ // }
+ // repeated ValueEntry value = 1 [enforce_utf8 = false];
+ // }
+ //
+ // TODO(xiaofeng): Remove this when the "enforce_utf8" option is removed
+ // from protocol compiler.
+ for (int i = 0; i < field->options().uninterpreted_option_size(); ++i) {
+ const UninterpretedOption& option =
+ field->options().uninterpreted_option(i);
+ if (option.name_size() == 1 &&
+ option.name(0).name_part() == "enforce_utf8" &&
+ !option.name(0).is_extension()) {
+ if (key_field->type() == FieldDescriptorProto::TYPE_STRING) {
+ key_field->mutable_options()->add_uninterpreted_option()->CopyFrom(
+ option);
+ }
+ if (value_field->type() == FieldDescriptorProto::TYPE_STRING) {
+ value_field->mutable_options()->add_uninterpreted_option()->CopyFrom(
+ option);
+ }
+ }
+ }
+}
+
+bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ if (!LookingAt("[")) return true;
+
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kOptionsFieldNumber);
+
+ DO(Consume("["));
+
+ // Parse field options.
+ do {
+ if (LookingAt("default")) {
+ // We intentionally pass field_location rather than location here, since
+ // the default value is not actually an option.
+ DO(ParseDefaultAssignment(field, field_location, containing_file));
+ } else if (LookingAt("json_name")) {
+ // Like default value, this "json_name" is not an actual option.
+ DO(ParseJsonName(field, field_location, containing_file));
+ } else {
+ DO(ParseOption(field->mutable_options(), location, containing_file,
+ OPTION_ASSIGNMENT));
+ }
+ } while (TryConsume(","));
+
+ DO(Consume("]"));
+ return true;
+}
+
+bool Parser::ParseDefaultAssignment(
+ FieldDescriptorProto* field, const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ if (field->has_default_value()) {
+ AddError("Already set option \"default\".");
+ field->clear_default_value();
+ }
+
+ DO(Consume("default"));
+ DO(Consume("="));
+
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kDefaultValueFieldNumber);
+ location.RecordLegacyLocation(field,
+ DescriptorPool::ErrorCollector::DEFAULT_VALUE);
+ std::string* default_value = field->mutable_default_value();
+
+ if (!field->has_type()) {
+ // The field has a type name, but we don't know if it is a message or an
+ // enum yet. (If it were a primitive type, |field| would have a type set
+ // already.) In this case, simply take the current string as the default
+ // value; we will catch the error later if it is not a valid enum value.
+ // (N.B. that we do not check whether the current token is an identifier:
+ // doing so throws strange errors when the user mistypes a primitive
+ // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default
+ // = 42]". In such a case the fundamental error is really that "int" is not
+ // a type, not that "42" is not an identifier. See b/12533582.)
+ *default_value = input_->current().text;
+ input_->Next();
+ return true;
+ }
+
+ switch (field->type()) {
+ case FieldDescriptorProto::TYPE_INT32:
+ case FieldDescriptorProto::TYPE_INT64:
+ case FieldDescriptorProto::TYPE_SINT32:
+ case FieldDescriptorProto::TYPE_SINT64:
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ case FieldDescriptorProto::TYPE_SFIXED64: {
+ uint64_t max_value = std::numeric_limits<int64_t>::max();
+ if (field->type() == FieldDescriptorProto::TYPE_INT32 ||
+ field->type() == FieldDescriptorProto::TYPE_SINT32 ||
+ field->type() == FieldDescriptorProto::TYPE_SFIXED32) {
+ max_value = std::numeric_limits<int32_t>::max();
+ }
+
+ // These types can be negative.
+ if (TryConsume("-")) {
+ default_value->append("-");
+ // Two's complement always has one more negative value than positive.
+ ++max_value;
+ }
+ // Parse the integer to verify that it is not out-of-range.
+ uint64_t value;
+ DO(ConsumeInteger64(max_value, &value,
+ "Expected integer for field default value."));
+ // And stringify it again.
+ default_value->append(StrCat(value));
+ break;
+ }
+
+ case FieldDescriptorProto::TYPE_UINT32:
+ case FieldDescriptorProto::TYPE_UINT64:
+ case FieldDescriptorProto::TYPE_FIXED32:
+ case FieldDescriptorProto::TYPE_FIXED64: {
+ uint64_t max_value = std::numeric_limits<uint64_t>::max();
+ if (field->type() == FieldDescriptorProto::TYPE_UINT32 ||
+ field->type() == FieldDescriptorProto::TYPE_FIXED32) {
+ max_value = std::numeric_limits<uint32_t>::max();
+ }
+
+ // Numeric, not negative.
+ if (TryConsume("-")) {
+ AddError("Unsigned field can't have negative default value.");
+ }
+ // Parse the integer to verify that it is not out-of-range.
+ uint64_t value;
+ DO(ConsumeInteger64(max_value, &value,
+ "Expected integer for field default value."));
+ // And stringify it again.
+ default_value->append(StrCat(value));
+ break;
+ }
+
+ case FieldDescriptorProto::TYPE_FLOAT:
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ // These types can be negative.
+ if (TryConsume("-")) {
+ default_value->append("-");
+ }
+ // Parse the integer because we have to convert hex integers to decimal
+ // floats.
+ double value;
+ DO(ConsumeNumber(&value, "Expected number."));
+ // And stringify it again.
+ default_value->append(SimpleDtoa(value));
+ break;
+
+ case FieldDescriptorProto::TYPE_BOOL:
+ if (TryConsume("true")) {
+ default_value->assign("true");
+ } else if (TryConsume("false")) {
+ default_value->assign("false");
+ } else {
+ AddError("Expected \"true\" or \"false\".");
+ return false;
+ }
+ break;
+
+ case FieldDescriptorProto::TYPE_STRING:
+ // Note: When file option java_string_check_utf8 is true, if a
+ // non-string representation (eg byte[]) is later supported, it must
+ // be checked for UTF-8-ness.
+ DO(ConsumeString(default_value,
+ "Expected string for field default "
+ "value."));
+ break;
+
+ case FieldDescriptorProto::TYPE_BYTES:
+ DO(ConsumeString(default_value, "Expected string."));
+ *default_value = CEscape(*default_value);
+ break;
+
+ case FieldDescriptorProto::TYPE_ENUM:
+ DO(ConsumeIdentifier(default_value,
+ "Expected enum identifier for field "
+ "default value."));
+ break;
+
+ case FieldDescriptorProto::TYPE_MESSAGE:
+ case FieldDescriptorProto::TYPE_GROUP:
+ AddError("Messages can't have default values.");
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::ParseJsonName(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ if (field->has_json_name()) {
+ AddError("Already set option \"json_name\".");
+ field->clear_json_name();
+ }
+
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kJsonNameFieldNumber);
+ location.RecordLegacyLocation(field,
+ DescriptorPool::ErrorCollector::OPTION_NAME);
+
+ DO(Consume("json_name"));
+ DO(Consume("="));
+
+ LocationRecorder value_location(location);
+ value_location.RecordLegacyLocation(
+ field, DescriptorPool::ErrorCollector::OPTION_VALUE);
+
+ DO(ConsumeString(field->mutable_json_name(),
+ "Expected string for JSON name."));
+ return true;
+}
+
+bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+ const LocationRecorder& part_location,
+ const FileDescriptorProto* containing_file) {
+ UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
+ std::string identifier; // We parse identifiers into this string.
+ if (LookingAt("(")) { // This is an extension.
+ DO(Consume("("));
+
+ {
+ LocationRecorder location(
+ part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+ // An extension name consists of dot-separated identifiers, and may begin
+ // with a dot.
+ if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+ DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+ name->mutable_name_part()->append(identifier);
+ }
+ while (LookingAt(".")) {
+ DO(Consume("."));
+ name->mutable_name_part()->append(".");
+ DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+ name->mutable_name_part()->append(identifier);
+ }
+ }
+
+ DO(Consume(")"));
+ name->set_is_extension(true);
+ } else { // This is a regular field.
+ LocationRecorder location(
+ part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+ DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+ name->mutable_name_part()->append(identifier);
+ name->set_is_extension(false);
+ }
+ return true;
+}
+
+bool Parser::ParseUninterpretedBlock(std::string* value) {
+ // Note that enclosing braces are not added to *value.
+ // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting
+ // an expression, not a block of statements.
+ DO(Consume("{"));
+ int brace_depth = 1;
+ while (!AtEnd()) {
+ if (LookingAt("{")) {
+ brace_depth++;
+ } else if (LookingAt("}")) {
+ brace_depth--;
+ if (brace_depth == 0) {
+ input_->Next();
+ return true;
+ }
+ }
+ // TODO(sanjay): Interpret line/column numbers to preserve formatting
+ if (!value->empty()) value->push_back(' ');
+ value->append(input_->current().text);
+ input_->Next();
+ }
+ AddError("Unexpected end of stream while parsing aggregate value.");
+ return false;
+}
+
+// We don't interpret the option here. Instead we store it in an
+// UninterpretedOption, to be interpreted later.
+bool Parser::ParseOption(Message* options,
+ const LocationRecorder& options_location,
+ const FileDescriptorProto* containing_file,
+ OptionStyle style) {
+ // Create an entry in the uninterpreted_option field.
+ const FieldDescriptor* uninterpreted_option_field =
+ options->GetDescriptor()->FindFieldByName("uninterpreted_option");
+ GOOGLE_CHECK(uninterpreted_option_field != NULL)
+ << "No field named \"uninterpreted_option\" in the Options proto.";
+
+ const Reflection* reflection = options->GetReflection();
+
+ LocationRecorder location(
+ options_location, uninterpreted_option_field->number(),
+ reflection->FieldSize(*options, uninterpreted_option_field));
+
+ if (style == OPTION_STATEMENT) {
+ DO(Consume("option"));
+ }
+
+ UninterpretedOption* uninterpreted_option =
+ down_cast<UninterpretedOption*>(options->GetReflection()->AddMessage(
+ options, uninterpreted_option_field));
+
+ // Parse dot-separated name.
+ {
+ LocationRecorder name_location(location,
+ UninterpretedOption::kNameFieldNumber);
+ name_location.RecordLegacyLocation(
+ uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME);
+
+ {
+ LocationRecorder part_location(name_location,
+ uninterpreted_option->name_size());
+ DO(ParseOptionNamePart(uninterpreted_option, part_location,
+ containing_file));
+ }
+
+ while (LookingAt(".")) {
+ DO(Consume("."));
+ LocationRecorder part_location(name_location,
+ uninterpreted_option->name_size());
+ DO(ParseOptionNamePart(uninterpreted_option, part_location,
+ containing_file));
+ }
+ }
+
+ DO(Consume("="));
+
+ {
+ LocationRecorder value_location(location);
+ value_location.RecordLegacyLocation(
+ uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
+
+ // All values are a single token, except for negative numbers, which consist
+ // of a single '-' symbol, followed by a positive number.
+ bool is_negative = TryConsume("-");
+
+ switch (input_->current().type) {
+ case io::Tokenizer::TYPE_START:
+ GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
+ return false;
+
+ case io::Tokenizer::TYPE_END:
+ AddError("Unexpected end of stream while parsing option value.");
+ return false;
+
+ case io::Tokenizer::TYPE_WHITESPACE:
+ case io::Tokenizer::TYPE_NEWLINE:
+ GOOGLE_CHECK(!input_->report_whitespace() && !input_->report_newlines())
+ << "Whitespace tokens were not requested.";
+ GOOGLE_LOG(FATAL) << "Tokenizer reported whitespace.";
+ return false;
+
+ case io::Tokenizer::TYPE_IDENTIFIER: {
+ value_location.AddPath(
+ UninterpretedOption::kIdentifierValueFieldNumber);
+ if (is_negative) {
+ AddError("Invalid '-' symbol before identifier.");
+ return false;
+ }
+ std::string value;
+ DO(ConsumeIdentifier(&value, "Expected identifier."));
+ uninterpreted_option->set_identifier_value(value);
+ break;
+ }
+
+ case io::Tokenizer::TYPE_INTEGER: {
+ uint64_t value;
+ uint64_t max_value =
+ is_negative
+ ? static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1
+ : std::numeric_limits<uint64_t>::max();
+ DO(ConsumeInteger64(max_value, &value, "Expected integer."));
+ if (is_negative) {
+ value_location.AddPath(
+ UninterpretedOption::kNegativeIntValueFieldNumber);
+ uninterpreted_option->set_negative_int_value(
+ static_cast<int64_t>(0 - value));
+ } else {
+ value_location.AddPath(
+ UninterpretedOption::kPositiveIntValueFieldNumber);
+ uninterpreted_option->set_positive_int_value(value);
+ }
+ break;
+ }
+
+ case io::Tokenizer::TYPE_FLOAT: {
+ value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
+ double value;
+ DO(ConsumeNumber(&value, "Expected number."));
+ uninterpreted_option->set_double_value(is_negative ? -value : value);
+ break;
+ }
+
+ case io::Tokenizer::TYPE_STRING: {
+ value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
+ if (is_negative) {
+ AddError("Invalid '-' symbol before string.");
+ return false;
+ }
+ std::string value;
+ DO(ConsumeString(&value, "Expected string."));
+ uninterpreted_option->set_string_value(value);
+ break;
+ }
+
+ case io::Tokenizer::TYPE_SYMBOL:
+ if (LookingAt("{")) {
+ value_location.AddPath(
+ UninterpretedOption::kAggregateValueFieldNumber);
+ DO(ParseUninterpretedBlock(
+ uninterpreted_option->mutable_aggregate_value()));
+ } else {
+ AddError("Expected option value.");
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (style == OPTION_STATEMENT) {
+ DO(ConsumeEndOfDeclaration(";", &location));
+ }
+
+ return true;
+}
+
+bool Parser::ParseExtensions(DescriptorProto* message,
+ const LocationRecorder& extensions_location,
+ const FileDescriptorProto* containing_file) {
+ // Parse the declaration.
+ DO(Consume("extensions"));
+
+ int old_range_size = message->extension_range_size();
+
+ do {
+ // Note that kExtensionRangeFieldNumber was already pushed by the parent.
+ LocationRecorder location(extensions_location,
+ message->extension_range_size());
+
+ DescriptorProto::ExtensionRange* range = message->add_extension_range();
+ location.RecordLegacyLocation(range,
+ DescriptorPool::ErrorCollector::NUMBER);
+
+ int start, end;
+ io::Tokenizer::Token start_token;
+
+ {
+ LocationRecorder start_location(
+ location, DescriptorProto::ExtensionRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeInteger(&start, "Expected field number range."));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+ if (TryConsume("max")) {
+ // Set to the sentinel value - 1 since we increment the value below.
+ // The actual value of the end of the range should be set with
+ // AdjustExtensionRangesWithMaxEndNumber.
+ end = kMaxRangeSentinel - 1;
+ } else {
+ DO(ConsumeInteger(&end, "Expected integer."));
+ }
+ } else {
+ LocationRecorder end_location(
+ location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ // Users like to specify inclusive ranges, but in code we like the end
+ // number to be exclusive.
+ ++end;
+
+ range->set_start(start);
+ range->set_end(end);
+ } while (TryConsume(","));
+
+ if (LookingAt("[")) {
+ int range_number_index = extensions_location.CurrentPathSize();
+ SourceCodeInfo info;
+
+ // Parse extension range options in the first range.
+ ExtensionRangeOptions* options =
+ message->mutable_extension_range(old_range_size)->mutable_options();
+
+ {
+ LocationRecorder index_location(
+ extensions_location, 0 /* we fill this in w/ actual index below */,
+ &info);
+ LocationRecorder location(
+ index_location, DescriptorProto::ExtensionRange::kOptionsFieldNumber);
+ DO(Consume("["));
+
+ do {
+ DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT));
+ } while (TryConsume(","));
+
+ DO(Consume("]"));
+ }
+
+ // Then copy the extension range options to all of the other ranges we've
+ // parsed.
+ for (int i = old_range_size + 1; i < message->extension_range_size(); i++) {
+ message->mutable_extension_range(i)->mutable_options()->CopyFrom(
+ *options);
+ }
+ // and copy source locations to the other ranges, too
+ for (int i = old_range_size; i < message->extension_range_size(); i++) {
+ for (int j = 0; j < info.location_size(); j++) {
+ if (info.location(j).path_size() == range_number_index + 1) {
+ // this location's path is up to the extension range index, but
+ // doesn't include options; so it's redundant with location above
+ continue;
+ }
+ SourceCodeInfo_Location* dest = source_code_info_->add_location();
+ *dest = info.location(j);
+ dest->set_path(range_number_index, i);
+ }
+ }
+ }
+
+ DO(ConsumeEndOfDeclaration(";", &extensions_location));
+ return true;
+}
+
+// This is similar to extension range parsing, except that it accepts field
+// name literals.
+bool Parser::ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location) {
+ io::Tokenizer::Token start_token = input_->current();
+ // Parse the declaration.
+ DO(Consume("reserved"));
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedNameFieldNumber);
+ location.StartAt(start_token);
+ return ParseReservedNames(message, location);
+ } else {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedRangeFieldNumber);
+ location.StartAt(start_token);
+ return ParseReservedNumbers(message, location);
+ }
+}
+
+bool Parser::ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ do {
+ LocationRecorder location(parent_location, message->reserved_name_size());
+ DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
+ } while (TryConsume(","));
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ bool first = true;
+ do {
+ LocationRecorder location(parent_location, message->reserved_range_size());
+
+ DescriptorProto::ReservedRange* range = message->add_reserved_range();
+ int start, end;
+ io::Tokenizer::Token start_token;
+ {
+ LocationRecorder start_location(
+ location, DescriptorProto::ReservedRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeInteger(&start, (first ? "Expected field name or number range."
+ : "Expected field number range.")));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ if (TryConsume("max")) {
+ // Set to the sentinel value - 1 since we increment the value below.
+ // The actual value of the end of the range should be set with
+ // AdjustExtensionRangesWithMaxEndNumber.
+ end = kMaxRangeSentinel - 1;
+ } else {
+ DO(ConsumeInteger(&end, "Expected integer."));
+ }
+ } else {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ // Users like to specify inclusive ranges, but in code we like the end
+ // number to be exclusive.
+ ++end;
+
+ range->set_start(start);
+ range->set_end(end);
+ first = false;
+ } while (TryConsume(","));
+
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReserved(EnumDescriptorProto* message,
+ const LocationRecorder& message_location) {
+ io::Tokenizer::Token start_token = input_->current();
+ // Parse the declaration.
+ DO(Consume("reserved"));
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ LocationRecorder location(message_location,
+ EnumDescriptorProto::kReservedNameFieldNumber);
+ location.StartAt(start_token);
+ return ParseReservedNames(message, location);
+ } else {
+ LocationRecorder location(message_location,
+ EnumDescriptorProto::kReservedRangeFieldNumber);
+ location.StartAt(start_token);
+ return ParseReservedNumbers(message, location);
+ }
+}
+
+bool Parser::ParseReservedNames(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ do {
+ LocationRecorder location(parent_location, message->reserved_name_size());
+ DO(ConsumeString(message->add_reserved_name(), "Expected enum value."));
+ } while (TryConsume(","));
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReservedNumbers(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ bool first = true;
+ do {
+ LocationRecorder location(parent_location, message->reserved_range_size());
+
+ EnumDescriptorProto::EnumReservedRange* range =
+ message->add_reserved_range();
+ int start, end;
+ io::Tokenizer::Token start_token;
+ {
+ LocationRecorder start_location(
+ location, EnumDescriptorProto::EnumReservedRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeSignedInteger(&start,
+ (first ? "Expected enum value or number range."
+ : "Expected enum number range.")));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+ if (TryConsume("max")) {
+ // This is in the enum descriptor path, which doesn't have the message
+ // set duality to fix up, so it doesn't integrate with the sentinel.
+ end = INT_MAX;
+ } else {
+ DO(ConsumeSignedInteger(&end, "Expected integer."));
+ }
+ } else {
+ LocationRecorder end_location(
+ location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ range->set_start(start);
+ range->set_end(end);
+ first = false;
+ } while (TryConsume(","));
+
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
+ RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& extend_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("extend"));
+
+ // Parse the extendee type.
+ io::Tokenizer::Token extendee_start = input_->current();
+ std::string extendee;
+ DO(ParseUserDefinedType(&extendee));
+ io::Tokenizer::Token extendee_end = input_->previous();
+
+ // Parse the block.
+ DO(ConsumeEndOfDeclaration("{", &extend_location));
+
+ bool is_first = true;
+
+ do {
+ if (AtEnd()) {
+ AddError("Reached end of input in extend definition (missing '}').");
+ return false;
+ }
+
+ // Note that kExtensionFieldNumber was already pushed by the parent.
+ LocationRecorder location(extend_location, extensions->size());
+
+ FieldDescriptorProto* field = extensions->Add();
+
+ {
+ LocationRecorder extendee_location(
+ location, FieldDescriptorProto::kExtendeeFieldNumber);
+ extendee_location.StartAt(extendee_start);
+ extendee_location.EndAt(extendee_end);
+
+ if (is_first) {
+ extendee_location.RecordLegacyLocation(
+ field, DescriptorPool::ErrorCollector::EXTENDEE);
+ is_first = false;
+ }
+ }
+
+ field->set_extendee(extendee);
+
+ if (!ParseMessageField(field, messages, parent_location,
+ location_field_number_for_nested_type, location,
+ containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ } while (!TryConsumeEndOfDeclaration("}", NULL));
+
+ return true;
+}
+
+bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl,
+ DescriptorProto* containing_type, int oneof_index,
+ const LocationRecorder& oneof_location,
+ const LocationRecorder& containing_type_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("oneof"));
+
+ {
+ LocationRecorder name_location(oneof_location,
+ OneofDescriptorProto::kNameFieldNumber);
+ DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name."));
+ }
+
+ DO(ConsumeEndOfDeclaration("{", &oneof_location));
+
+ do {
+ if (AtEnd()) {
+ AddError("Reached end of input in oneof definition (missing '}').");
+ return false;
+ }
+
+ if (LookingAt("option")) {
+ LocationRecorder option_location(
+ oneof_location, OneofDescriptorProto::kOptionsFieldNumber);
+ if (!ParseOption(oneof_decl->mutable_options(), option_location,
+ containing_file, OPTION_STATEMENT)) {
+ return false;
+ }
+ continue;
+ }
+
+ // Print a nice error if the user accidentally tries to place a label
+ // on an individual member of a oneof.
+ if (LookingAt("required") || LookingAt("optional") ||
+ LookingAt("repeated")) {
+ AddError(
+ "Fields in oneofs must not have labels (required / optional "
+ "/ repeated).");
+ // We can continue parsing here because we understand what the user
+ // meant. The error report will still make parsing fail overall.
+ input_->Next();
+ }
+
+ LocationRecorder field_location(containing_type_location,
+ DescriptorProto::kFieldFieldNumber,
+ containing_type->field_size());
+
+ FieldDescriptorProto* field = containing_type->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_oneof_index(oneof_index);
+
+ if (!ParseMessageFieldNoLabel(field, containing_type->mutable_nested_type(),
+ containing_type_location,
+ DescriptorProto::kNestedTypeFieldNumber,
+ field_location, containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ } while (!TryConsumeEndOfDeclaration("}", NULL));
+
+ return true;
+}
+
+// -------------------------------------------------------------------
+// Enums
+
+bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("enum"));
+
+ {
+ LocationRecorder location(enum_location,
+ EnumDescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(enum_type,
+ DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
+ }
+
+ DO(ParseEnumBlock(enum_type, enum_location, containing_file));
+
+ DO(ValidateEnum(enum_type));
+
+ return true;
+}
+
+bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
+ DO(ConsumeEndOfDeclaration("{", &enum_location));
+
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
+ if (AtEnd()) {
+ AddError("Reached end of input in enum definition (missing '}').");
+ return false;
+ }
+
+ if (!ParseEnumStatement(enum_type, enum_location, containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ }
+
+ return true;
+}
+
+bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ return true;
+ } else if (LookingAt("option")) {
+ LocationRecorder location(enum_location,
+ EnumDescriptorProto::kOptionsFieldNumber);
+ return ParseOption(enum_type->mutable_options(), location, containing_file,
+ OPTION_STATEMENT);
+ } else if (LookingAt("reserved")) {
+ return ParseReserved(enum_type, enum_location);
+ } else {
+ LocationRecorder location(enum_location,
+ EnumDescriptorProto::kValueFieldNumber,
+ enum_type->value_size());
+ return ParseEnumConstant(enum_type->add_value(), location, containing_file);
+ }
+}
+
+bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file) {
+ // Parse name.
+ {
+ LocationRecorder location(enum_value_location,
+ EnumValueDescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(enum_value,
+ DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(enum_value->mutable_name(),
+ "Expected enum constant name."));
+ }
+
+ DO(Consume("=", "Missing numeric value for enum constant."));
+
+ // Parse value.
+ {
+ LocationRecorder location(enum_value_location,
+ EnumValueDescriptorProto::kNumberFieldNumber);
+ location.RecordLegacyLocation(enum_value,
+ DescriptorPool::ErrorCollector::NUMBER);
+
+ int number;
+ DO(ConsumeSignedInteger(&number, "Expected integer."));
+ enum_value->set_number(number);
+ }
+
+ DO(ParseEnumConstantOptions(enum_value, enum_value_location,
+ containing_file));
+
+ DO(ConsumeEndOfDeclaration(";", &enum_value_location));
+
+ return true;
+}
+
+bool Parser::ParseEnumConstantOptions(
+ EnumValueDescriptorProto* value,
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file) {
+ if (!LookingAt("[")) return true;
+
+ LocationRecorder location(enum_value_location,
+ EnumValueDescriptorProto::kOptionsFieldNumber);
+
+ DO(Consume("["));
+
+ do {
+ DO(ParseOption(value->mutable_options(), location, containing_file,
+ OPTION_ASSIGNMENT));
+ } while (TryConsume(","));
+
+ DO(Consume("]"));
+ return true;
+}
+
+// -------------------------------------------------------------------
+// Services
+
+bool Parser::ParseServiceDefinition(
+ ServiceDescriptorProto* service, const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("service"));
+
+ {
+ LocationRecorder location(service_location,
+ ServiceDescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(service,
+ DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
+ }
+
+ DO(ParseServiceBlock(service, service_location, containing_file));
+ return true;
+}
+
+bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
+ DO(ConsumeEndOfDeclaration("{", &service_location));
+
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
+ if (AtEnd()) {
+ AddError("Reached end of input in service definition (missing '}').");
+ return false;
+ }
+
+ if (!ParseServiceStatement(service, service_location, containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ }
+
+ return true;
+}
+
+bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ return true;
+ } else if (LookingAt("option")) {
+ LocationRecorder location(service_location,
+ ServiceDescriptorProto::kOptionsFieldNumber);
+ return ParseOption(service->mutable_options(), location, containing_file,
+ OPTION_STATEMENT);
+ } else {
+ LocationRecorder location(service_location,
+ ServiceDescriptorProto::kMethodFieldNumber,
+ service->method_size());
+ return ParseServiceMethod(service->add_method(), location, containing_file);
+ }
+}
+
+bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
+ const LocationRecorder& method_location,
+ const FileDescriptorProto* containing_file) {
+ DO(Consume("rpc"));
+
+ {
+ LocationRecorder location(method_location,
+ MethodDescriptorProto::kNameFieldNumber);
+ location.RecordLegacyLocation(method, DescriptorPool::ErrorCollector::NAME);
+ DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+ }
+
+ // Parse input type.
+ DO(Consume("("));
+ {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
+ location.RecordLegacyLocation(method,
+ DescriptorPool::ErrorCollector::OTHER);
+ method->set_client_streaming(true);
+ DO(Consume("stream"));
+
+ }
+ LocationRecorder location(method_location,
+ MethodDescriptorProto::kInputTypeFieldNumber);
+ location.RecordLegacyLocation(method,
+ DescriptorPool::ErrorCollector::INPUT_TYPE);
+ DO(ParseUserDefinedType(method->mutable_input_type()));
+ }
+ DO(Consume(")"));
+
+ // Parse output type.
+ DO(Consume("returns"));
+ DO(Consume("("));
+ {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
+ location.RecordLegacyLocation(method,
+ DescriptorPool::ErrorCollector::OTHER);
+ DO(Consume("stream"));
+ method->set_server_streaming(true);
+
+ }
+ LocationRecorder location(method_location,
+ MethodDescriptorProto::kOutputTypeFieldNumber);
+ location.RecordLegacyLocation(method,
+ DescriptorPool::ErrorCollector::OUTPUT_TYPE);
+ DO(ParseUserDefinedType(method->mutable_output_type()));
+ }
+ DO(Consume(")"));
+
+ if (LookingAt("{")) {
+ // Options!
+ DO(ParseMethodOptions(method_location, containing_file,
+ MethodDescriptorProto::kOptionsFieldNumber,
+ method->mutable_options()));
+ } else {
+ DO(ConsumeEndOfDeclaration(";", &method_location));
+ }
+
+ return true;
+}
+
+bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options) {
+ // Options!
+ ConsumeEndOfDeclaration("{", &parent_location);
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
+ if (AtEnd()) {
+ AddError("Reached end of input in method options (missing '}').");
+ return false;
+ }
+
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ } else {
+ LocationRecorder location(parent_location, optionsFieldNumber);
+ if (!ParseOption(mutable_options, location, containing_file,
+ OPTION_STATEMENT)) {
+ // This statement failed to parse. Skip it, but keep looping to
+ // parse other statements.
+ SkipStatement();
+ }
+ }
+ }
+
+ return true;
+}
+
+// -------------------------------------------------------------------
+
+bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
+ if (!LookingAt("optional") && !LookingAt("repeated") &&
+ !LookingAt("required")) {
+ return false;
+ }
+ LocationRecorder location(field_location,
+ FieldDescriptorProto::kLabelFieldNumber);
+ if (TryConsume("optional")) {
+ *label = FieldDescriptorProto::LABEL_OPTIONAL;
+ } else if (TryConsume("repeated")) {
+ *label = FieldDescriptorProto::LABEL_REPEATED;
+ } else {
+ Consume("required");
+ *label = FieldDescriptorProto::LABEL_REQUIRED;
+ }
+ return true;
+}
+
+bool Parser::ParseType(FieldDescriptorProto::Type* type,
+ std::string* type_name) {
+ TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
+ if (iter != kTypeNames.end()) {
+ *type = iter->second;
+ input_->Next();
+ } else {
+ DO(ParseUserDefinedType(type_name));
+ }
+ return true;
+}
+
+bool Parser::ParseUserDefinedType(std::string* type_name) {
+ type_name->clear();
+
+ TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
+ if (iter != kTypeNames.end()) {
+ // Note: The only place enum types are allowed is for field types, but
+ // if we are parsing a field type then we would not get here because
+ // primitives are allowed there as well. So this error message doesn't
+ // need to account for enums.
+ AddError("Expected message type.");
+
+ // Pretend to accept this type so that we can go on parsing.
+ *type_name = input_->current().text;
+ input_->Next();
+ return true;
+ }
+
+ // A leading "." means the name is fully-qualified.
+ if (TryConsume(".")) type_name->append(".");
+
+ // Consume the first part of the name.
+ std::string identifier;
+ DO(ConsumeIdentifier(&identifier, "Expected type name."));
+ type_name->append(identifier);
+
+ // Consume more parts.
+ while (TryConsume(".")) {
+ type_name->append(".");
+ DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+ type_name->append(identifier);
+ }
+
+ return true;
+}
+
+// ===================================================================
+
+bool Parser::ParsePackage(FileDescriptorProto* file,
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file) {
+ if (file->has_package()) {
+ AddError("Multiple package definitions.");
+ // Don't append the new package to the old one. Just replace it. Not
+ // that it really matters since this is an error anyway.
+ file->clear_package();
+ }
+
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kPackageFieldNumber);
+ location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME);
+
+ DO(Consume("package"));
+
+ while (true) {
+ std::string identifier;
+ DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+ file->mutable_package()->append(identifier);
+ if (!TryConsume(".")) break;
+ file->mutable_package()->append(".");
+ }
+
+ DO(ConsumeEndOfDeclaration(";", &location));
+
+ return true;
+}
+
+bool Parser::ParseImport(RepeatedPtrField<std::string>* dependency,
+ RepeatedField<int32_t>* public_dependency,
+ RepeatedField<int32_t>* weak_dependency,
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file) {
+ LocationRecorder location(root_location,
+ FileDescriptorProto::kDependencyFieldNumber,
+ dependency->size());
+
+ DO(Consume("import"));
+
+ if (LookingAt("public")) {
+ LocationRecorder public_location(
+ root_location, FileDescriptorProto::kPublicDependencyFieldNumber,
+ public_dependency->size());
+ DO(Consume("public"));
+ *public_dependency->Add() = dependency->size();
+ } else if (LookingAt("weak")) {
+ LocationRecorder weak_location(
+ root_location, FileDescriptorProto::kWeakDependencyFieldNumber,
+ weak_dependency->size());
+ weak_location.RecordLegacyImportLocation(containing_file, "weak");
+ DO(Consume("weak"));
+ *weak_dependency->Add() = dependency->size();
+ }
+
+ std::string import_file;
+ DO(ConsumeString(&import_file,
+ "Expected a string naming the file to import."));
+ *dependency->Add() = import_file;
+ location.RecordLegacyImportLocation(containing_file, import_file);
+
+ DO(ConsumeEndOfDeclaration(";", &location));
+
+ return true;
+}
+
+// ===================================================================
+
+SourceLocationTable::SourceLocationTable() {}
+SourceLocationTable::~SourceLocationTable() {}
+
+bool SourceLocationTable::Find(
+ const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
+ int* column) const {
+ const std::pair<int, int>* result =
+ FindOrNull(location_map_, std::make_pair(descriptor, location));
+ if (result == NULL) {
+ *line = -1;
+ *column = 0;
+ return false;
+ } else {
+ *line = result->first;
+ *column = result->second;
+ return true;
+ }
+}
+
+bool SourceLocationTable::FindImport(const Message* descriptor,
+ const std::string& name, int* line,
+ int* column) const {
+ const std::pair<int, int>* result =
+ FindOrNull(import_location_map_, std::make_pair(descriptor, name));
+ if (result == nullptr) {
+ *line = -1;
+ *column = 0;
+ return false;
+ } else {
+ *line = result->first;
+ *column = result->second;
+ return true;
+ }
+}
+
+void SourceLocationTable::Add(
+ const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location, int line,
+ int column) {
+ location_map_[std::make_pair(descriptor, location)] =
+ std::make_pair(line, column);
+}
+
+void SourceLocationTable::AddImport(const Message* descriptor,
+ const std::string& name, int line,
+ int column) {
+ import_location_map_[std::make_pair(descriptor, name)] =
+ std::make_pair(line, column);
+}
+
+void SourceLocationTable::Clear() { location_map_.clear(); }
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/parser.h b/NorthstarDedicatedTest/include/protobuf/compiler/parser.h
new file mode 100644
index 00000000..37055bd3
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/parser.h
@@ -0,0 +1,603 @@
+// 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.
+//
+// Implements parsing of .proto files to FileDescriptorProtos.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
+#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
+
+#include <cstdint>
+#include <map>
+#include <string>
+#include <utility>
+
+#include <descriptor.pb.h>
+#include <io/tokenizer.h>
+#include <descriptor.h>
+#include <repeated_field.h>
+
+// Must be included last.
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace compiler {
+
+// Defined in this file.
+class Parser;
+class SourceLocationTable;
+
+// Implements parsing of protocol definitions (such as .proto files).
+//
+// Note that most users will be more interested in the Importer class.
+// Parser is a lower-level class which simply converts a single .proto file
+// to a FileDescriptorProto. It does not resolve import directives or perform
+// many other kinds of validation needed to construct a complete
+// FileDescriptor.
+class PROTOBUF_EXPORT Parser {
+ public:
+ Parser();
+ ~Parser();
+
+ // Parse the entire input and construct a FileDescriptorProto representing
+ // it. Returns true if no errors occurred, false otherwise.
+ bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
+
+ // Optional features:
+
+ // DEPRECATED: New code should use the SourceCodeInfo embedded in the
+ // FileDescriptorProto.
+ //
+ // Requests that locations of certain definitions be recorded to the given
+ // SourceLocationTable while parsing. This can be used to look up exact line
+ // and column numbers for errors reported by DescriptorPool during validation.
+ // Set to NULL (the default) to discard source location information.
+ void RecordSourceLocationsTo(SourceLocationTable* location_table) {
+ source_location_table_ = location_table;
+ }
+
+ // Requests that errors be recorded to the given ErrorCollector while
+ // parsing. Set to NULL (the default) to discard error messages.
+ void RecordErrorsTo(io::ErrorCollector* error_collector) {
+ error_collector_ = error_collector;
+ }
+
+ // Returns the identifier used in the "syntax = " declaration, if one was
+ // seen during the last call to Parse(), or the empty string otherwise.
+ const std::string& GetSyntaxIdentifier() { return syntax_identifier_; }
+
+ // If set true, input files will be required to begin with a syntax
+ // identifier. Otherwise, files may omit this. If a syntax identifier
+ // is provided, it must be 'syntax = "proto2";' and must appear at the
+ // top of this file regardless of whether or not it was required.
+ void SetRequireSyntaxIdentifier(bool value) {
+ require_syntax_identifier_ = value;
+ }
+
+ // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
+ // parsing as soon as it has seen the syntax identifier, or lack thereof.
+ // This is useful for quickly identifying the syntax of the file without
+ // parsing the whole thing. If this is enabled, no error will be recorded
+ // if the syntax identifier is something other than "proto2" (since
+ // presumably the caller intends to deal with that), but other kinds of
+ // errors (e.g. parse errors) will still be reported. When this is enabled,
+ // you may pass a NULL FileDescriptorProto to Parse().
+ void SetStopAfterSyntaxIdentifier(bool value) {
+ stop_after_syntax_identifier_ = value;
+ }
+
+ private:
+ class LocationRecorder;
+
+ // =================================================================
+ // Error recovery helpers
+
+ // Consume the rest of the current statement. This consumes tokens
+ // until it sees one of:
+ // ';' Consumes the token and returns.
+ // '{' Consumes the brace then calls SkipRestOfBlock().
+ // '}' Returns without consuming.
+ // EOF Returns (can't consume).
+ // The Parser often calls SkipStatement() after encountering a syntax
+ // error. This allows it to go on parsing the following lines, allowing
+ // it to report more than just one error in the file.
+ void SkipStatement();
+
+ // Consume the rest of the current block, including nested blocks,
+ // ending after the closing '}' is encountered and consumed, or at EOF.
+ void SkipRestOfBlock();
+
+ // -----------------------------------------------------------------
+ // Single-token consuming helpers
+ //
+ // These make parsing code more readable.
+
+ // True if the current token is TYPE_END.
+ inline bool AtEnd();
+
+ // True if the next token matches the given text.
+ inline bool LookingAt(const char* text);
+ // True if the next token is of the given type.
+ inline bool LookingAtType(io::Tokenizer::TokenType token_type);
+
+ // If the next token exactly matches the text given, consume it and return
+ // true. Otherwise, return false without logging an error.
+ bool TryConsume(const char* text);
+
+ // These attempt to read some kind of token from the input. If successful,
+ // they return true. Otherwise they return false and add the given error
+ // to the error list.
+
+ // Consume a token with the exact text given.
+ bool Consume(const char* text, const char* error);
+ // Same as above, but automatically generates the error "Expected \"text\".",
+ // where "text" is the expected token text.
+ bool Consume(const char* text);
+ // Consume a token of type IDENTIFIER and store its text in "output".
+ bool ConsumeIdentifier(std::string* output, const char* error);
+ // Consume an integer and store its value in "output".
+ bool ConsumeInteger(int* output, const char* error);
+ // Consume a signed integer and store its value in "output".
+ bool ConsumeSignedInteger(int* output, const char* error);
+ // Consume a 64-bit integer and store its value in "output". If the value
+ // is greater than max_value, an error will be reported.
+ bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
+ const char* error);
+ // Consume a number and store its value in "output". This will accept
+ // tokens of either INTEGER or FLOAT type.
+ bool ConsumeNumber(double* output, const char* error);
+ // Consume a string literal and store its (unescaped) value in "output".
+ bool ConsumeString(std::string* output, const char* error);
+
+ // Consume a token representing the end of the statement. Comments between
+ // this token and the next will be harvested for documentation. The given
+ // LocationRecorder should refer to the declaration that was just parsed;
+ // it will be populated with these comments.
+ //
+ // TODO(kenton): The LocationRecorder is const because historically locations
+ // have been passed around by const reference, for no particularly good
+ // reason. We should probably go through and change them all to mutable
+ // pointer to make this more intuitive.
+ bool TryConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location);
+ bool TryConsumeEndOfDeclarationFinishScope(const char* text,
+ const LocationRecorder* location);
+
+ bool ConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location);
+
+ // -----------------------------------------------------------------
+ // Error logging helpers
+
+ // Invokes error_collector_->AddError(), if error_collector_ is not NULL.
+ void AddError(int line, int column, const std::string& error);
+
+ // Invokes error_collector_->AddError() with the line and column number
+ // of the current token.
+ void AddError(const std::string& error);
+
+ // Invokes error_collector_->AddWarning() with the line and column number
+ // of the current token.
+ void AddWarning(const std::string& warning);
+
+ // Records a location in the SourceCodeInfo.location table (see
+ // descriptor.proto). We use RAII to ensure that the start and end locations
+ // are recorded -- the constructor records the start location and the
+ // destructor records the end location. Since the parser is
+ // recursive-descent, this works out beautifully.
+ class PROTOBUF_EXPORT LocationRecorder {
+ public:
+ // Construct the file's "root" location.
+ LocationRecorder(Parser* parser);
+
+ // Construct a location that represents a declaration nested within the
+ // given parent. E.g. a field's location is nested within the location
+ // for a message type. The parent's path will be copied, so you should
+ // call AddPath() only to add the path components leading from the parent
+ // to the child (as opposed to leading from the root to the child).
+ LocationRecorder(const LocationRecorder& parent);
+
+ // Convenience constructors that call AddPath() one or two times.
+ LocationRecorder(const LocationRecorder& parent, int path1);
+ LocationRecorder(const LocationRecorder& parent, int path1, int path2);
+
+ // Creates a recorder that generates locations into given source code info.
+ LocationRecorder(const LocationRecorder& parent, int path1,
+ SourceCodeInfo* source_code_info);
+
+ ~LocationRecorder();
+
+ // Add a path component. See SourceCodeInfo.Location.path in
+ // descriptor.proto.
+ void AddPath(int path_component);
+
+ // By default the location is considered to start at the current token at
+ // the time the LocationRecorder is created. StartAt() sets the start
+ // location to the given token instead.
+ void StartAt(const io::Tokenizer::Token& token);
+
+ // Start at the same location as some other LocationRecorder.
+ void StartAt(const LocationRecorder& other);
+
+ // By default the location is considered to end at the previous token at
+ // the time the LocationRecorder is destroyed. EndAt() sets the end
+ // location to the given token instead.
+ void EndAt(const io::Tokenizer::Token& token);
+
+ // Records the start point of this location to the SourceLocationTable that
+ // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable
+ // is an older way of keeping track of source locations which is still
+ // used in some places.
+ void RecordLegacyLocation(
+ const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location);
+ void RecordLegacyImportLocation(const Message* descriptor,
+ const std::string& name);
+
+ // Returns the number of path components in the recorder's current location.
+ int CurrentPathSize() const;
+
+ // Attaches leading and trailing comments to the location. The two strings
+ // will be swapped into place, so after this is called *leading and
+ // *trailing will be empty.
+ //
+ // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
+ // why this is const.
+ void AttachComments(std::string* leading, std::string* trailing,
+ std::vector<std::string>* detached_comments) const;
+
+ private:
+ // Indexes of parent and current location in the parent
+ // SourceCodeInfo.location repeated field. For top-level elements,
+ // parent_index_ is -1.
+ Parser* parser_;
+ SourceCodeInfo* source_code_info_;
+ SourceCodeInfo::Location* location_;
+
+ void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info);
+ };
+
+ // =================================================================
+ // Parsers for various language constructs
+
+ // Parses the "syntax = \"proto2\";" line at the top of the file. Returns
+ // false if it failed to parse or if the syntax identifier was not
+ // recognized.
+ bool ParseSyntaxIdentifier(const LocationRecorder& parent);
+
+ // These methods parse various individual bits of code. They return
+ // false if they completely fail to parse the construct. In this case,
+ // it is probably necessary to skip the rest of the statement to recover.
+ // However, if these methods return true, it does NOT mean that there
+ // were no errors; only that there were no *syntax* errors. For instance,
+ // if a service method is defined using proper syntax but uses a primitive
+ // type as its input or output, ParseMethodField() still returns true
+ // and only reports the error by calling AddError(). In practice, this
+ // makes logic much simpler for the caller.
+
+ // Parse a top-level message, enum, service, etc.
+ bool ParseTopLevelStatement(FileDescriptorProto* file,
+ const LocationRecorder& root_location);
+
+ // Parse various language high-level language construrcts.
+ bool ParseMessageDefinition(DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseServiceDefinition(ServiceDescriptorProto* service,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file);
+ bool ParsePackage(FileDescriptorProto* file,
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseImport(RepeatedPtrField<std::string>* dependency,
+ RepeatedField<int32_t>* public_dependency,
+ RepeatedField<int32_t>* weak_dependency,
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file);
+
+ // These methods parse the contents of a message, enum, or service type and
+ // add them to the given object. They consume the entire block including
+ // the beginning and ending brace.
+ bool ParseMessageBlock(DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseEnumBlock(EnumDescriptorProto* enum_type,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseServiceBlock(ServiceDescriptorProto* service,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse one statement within a message, enum, or service block, including
+ // final semicolon.
+ bool ParseMessageStatement(DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseEnumStatement(EnumDescriptorProto* message,
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
+ bool ParseServiceStatement(ServiceDescriptorProto* message,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a field of a message. If the field is a group, its type will be
+ // added to "messages".
+ //
+ // parent_location and location_field_number_for_nested_type are needed when
+ // parsing groups -- we need to generate a nested message type within the
+ // parent and record its location accordingly. Since the parent could be
+ // either a FileDescriptorProto or a DescriptorProto, we must pass in the
+ // correct field number to use.
+ bool ParseMessageField(FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ // Like ParseMessageField() but expects the label has already been filled in
+ // by the caller.
+ bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse an "extensions" declaration.
+ bool ParseExtensions(DescriptorProto* message,
+ const LocationRecorder& extensions_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a "reserved" declaration.
+ bool ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location);
+ bool ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReserved(EnumDescriptorProto* message,
+ const LocationRecorder& message_location);
+ bool ParseReservedNames(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReservedNumbers(EnumDescriptorProto* message,
+ const LocationRecorder& parent_location);
+
+ // Parse an "extend" declaration. (See also comments for
+ // ParseMessageField().)
+ bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
+ RepeatedPtrField<DescriptorProto>* messages,
+ const LocationRecorder& parent_location,
+ int location_field_number_for_nested_type,
+ const LocationRecorder& extend_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a "oneof" declaration. The caller is responsible for setting
+ // oneof_decl->label() since it will have had to parse the label before it
+ // knew it was parsing a oneof.
+ bool ParseOneof(OneofDescriptorProto* oneof_decl,
+ DescriptorProto* containing_type, int oneof_index,
+ const LocationRecorder& oneof_location,
+ const LocationRecorder& containing_type_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a single enum value within an enum block.
+ bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse enum constant options, i.e. the list in square brackets at the end
+ // of the enum constant value definition.
+ bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a single method within a service definition.
+ bool ParseServiceMethod(MethodDescriptorProto* method,
+ const LocationRecorder& method_location,
+ const FileDescriptorProto* containing_file);
+
+
+ // Parse options of a single method or stream.
+ bool ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options);
+
+ // Parse "required", "optional", or "repeated" and fill in "label"
+ // with the value. Returns true if such a label is consumed.
+ bool ParseLabel(FieldDescriptorProto::Label* label,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse a type name and fill in "type" (if it is a primitive) or
+ // "type_name" (if it is not) with the type parsed.
+ bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name);
+ // Parse a user-defined type and fill in "type_name" with the name.
+ // If a primitive type is named, it is treated as an error.
+ bool ParseUserDefinedType(std::string* type_name);
+
+ // Parses field options, i.e. the stuff in square brackets at the end
+ // of a field definition. Also parses default value.
+ bool ParseFieldOptions(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parse the "default" option. This needs special handling because its
+ // type is the field's type.
+ bool ParseDefaultAssignment(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ bool ParseJsonName(FieldDescriptorProto* field,
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
+
+ enum OptionStyle {
+ OPTION_ASSIGNMENT, // just "name = value"
+ OPTION_STATEMENT // "option name = value;"
+ };
+
+ // Parse a single option name/value pair, e.g. "ctype = CORD". The name
+ // identifies a field of the given Message, and the value of that field
+ // is set to the parsed value.
+ bool ParseOption(Message* options, const LocationRecorder& options_location,
+ const FileDescriptorProto* containing_file,
+ OptionStyle style);
+
+ // Parses a single part of a multipart option name. A multipart name consists
+ // of names separated by dots. Each name is either an identifier or a series
+ // of identifiers separated by dots and enclosed in parentheses. E.g.,
+ // "foo.(bar.baz).qux".
+ bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+ const LocationRecorder& part_location,
+ const FileDescriptorProto* containing_file);
+
+ // Parses a string surrounded by balanced braces. Strips off the outer
+ // braces and stores the enclosed string in *value.
+ // E.g.,
+ // { foo } *value gets 'foo'
+ // { foo { bar: box } } *value gets 'foo { bar: box }'
+ // {} *value gets ''
+ //
+ // REQUIRES: LookingAt("{")
+ // When finished successfully, we are looking at the first token past
+ // the ending brace.
+ bool ParseUninterpretedBlock(std::string* value);
+
+ struct MapField {
+ // Whether the field is a map field.
+ bool is_map_field;
+ // The types of the key and value if they are primitive types.
+ FieldDescriptorProto::Type key_type;
+ FieldDescriptorProto::Type value_type;
+ // Or the type names string if the types are customized types.
+ std::string key_type_name;
+ std::string value_type_name;
+
+ MapField() : is_map_field(false) {}
+ };
+ // Desugar the map syntax to generate a nested map entry message.
+ void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages);
+
+ // Whether fields without label default to optional fields.
+ bool DefaultToOptionalFields() const {
+ return syntax_identifier_ == "proto3";
+ }
+
+ bool ValidateEnum(const EnumDescriptorProto* proto);
+
+ // =================================================================
+
+ io::Tokenizer* input_;
+ io::ErrorCollector* error_collector_;
+ SourceCodeInfo* source_code_info_;
+ SourceLocationTable* source_location_table_; // legacy
+ bool had_errors_;
+ bool require_syntax_identifier_;
+ bool stop_after_syntax_identifier_;
+ std::string syntax_identifier_;
+
+ // Leading doc comments for the next declaration. These are not complete
+ // yet; use ConsumeEndOfDeclaration() to get the complete comments.
+ std::string upcoming_doc_comments_;
+
+ // Detached comments are not connected to any syntax entities. Elements in
+ // this vector are paragraphs of comments separated by empty lines. The
+ // detached comments will be put into the leading_detached_comments field for
+ // the next element (See SourceCodeInfo.Location in descriptor.proto), when
+ // ConsumeEndOfDeclaration() is called.
+ std::vector<std::string> upcoming_detached_comments_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
+};
+
+// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
+// DescriptorPool when validating descriptors -- to line and column numbers
+// within the original source code.
+//
+// This is semi-obsolete: FileDescriptorProto.source_code_info now contains
+// far more complete information about source locations. However, as of this
+// writing you still need to use SourceLocationTable when integrating with
+// DescriptorPool.
+class PROTOBUF_EXPORT SourceLocationTable {
+ public:
+ SourceLocationTable();
+ ~SourceLocationTable();
+
+ // Finds the precise location of the given error and fills in *line and
+ // *column with the line and column numbers. If not found, sets *line to
+ // -1 and *column to 0 (since line = -1 is used to mean "error has no exact
+ // location" in the ErrorCollector interface). Returns true if found, false
+ // otherwise.
+ bool Find(const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
+ int* column) const;
+ bool FindImport(const Message* descriptor, const std::string& name, int* line,
+ int* column) const;
+
+ // Adds a location to the table.
+ void Add(const Message* descriptor,
+ DescriptorPool::ErrorCollector::ErrorLocation location, int line,
+ int column);
+ void AddImport(const Message* descriptor, const std::string& name, int line,
+ int column);
+
+ // Clears the contents of the table.
+ void Clear();
+
+ private:
+ typedef std::map<
+ std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
+ std::pair<int, int> >
+ LocationMap;
+ LocationMap location_map_;
+ std::map<std::pair<const Message*, std::string>, std::pair<int, int> >
+ import_location_map_;
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/parser_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/parser_unittest.cc
new file mode 100644
index 00000000..0b175117
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/parser_unittest.cc
@@ -0,0 +1,3681 @@
+// 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 <compiler/parser.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <test_util2.h>
+#include <unittest.pb.h>
+#include <any.pb.h>
+#include <unittest_custom_options.pb.h>
+#include <io/tokenizer.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.pb.h>
+#include <text_format.h>
+#include <wire_format.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <stubs/substitute.h>
+#include <stubs/map_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+class MockErrorCollector : public io::ErrorCollector {
+ public:
+ MockErrorCollector() = default;
+ ~MockErrorCollector() override = default;
+
+ std::string warning_;
+ std::string text_;
+
+ // implements ErrorCollector ---------------------------------------
+ void AddWarning(int line, int column, const std::string& message) override {
+ strings::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message);
+ }
+
+ void AddError(int line, int column, const std::string& message) override {
+ strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
+ }
+};
+
+class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+ MockValidationErrorCollector(const SourceLocationTable& source_locations,
+ io::ErrorCollector* wrapped_collector)
+ : source_locations_(source_locations),
+ wrapped_collector_(wrapped_collector) {}
+ ~MockValidationErrorCollector() {}
+
+ // implements ErrorCollector ---------------------------------------
+ void AddError(const std::string& filename, const std::string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const std::string& message) override {
+ int line, column;
+ if (location == DescriptorPool::ErrorCollector::IMPORT) {
+ source_locations_.FindImport(descriptor, element_name, &line, &column);
+ } else {
+ source_locations_.Find(descriptor, location, &line, &column);
+ }
+ wrapped_collector_->AddError(line, column, message);
+ }
+
+ private:
+ const SourceLocationTable& source_locations_;
+ io::ErrorCollector* wrapped_collector_;
+};
+
+class ParserTest : public testing::Test {
+ protected:
+ ParserTest() : require_syntax_identifier_(false) {}
+
+ // Set up the parser to parse the given text.
+ void SetupParser(const char* text) {
+ raw_input_.reset(new io::ArrayInputStream(text, strlen(text)));
+ input_.reset(new io::Tokenizer(raw_input_.get(), &error_collector_));
+ parser_.reset(new Parser());
+ parser_->RecordErrorsTo(&error_collector_);
+ parser_->SetRequireSyntaxIdentifier(require_syntax_identifier_);
+ }
+
+ // Parse the input and expect that the resulting FileDescriptorProto matches
+ // the given output. The output is a FileDescriptorProto in protocol buffer
+ // text format.
+ void ExpectParsesTo(const char* input, const char* output) {
+ SetupParser(input);
+ FileDescriptorProto actual, expected;
+
+ parser_->Parse(input_.get(), &actual);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We don't cover SourceCodeInfo in these tests.
+ actual.clear_source_code_info();
+
+ // Parse the ASCII representation in order to canonicalize it. We could
+ // just compare directly to actual.DebugString(), but that would require
+ // that the caller precisely match the formatting that DebugString()
+ // produces.
+ ASSERT_TRUE(TextFormat::ParseFromString(output, &expected));
+
+ // Compare by comparing debug strings.
+ // TODO(kenton): Use differencer, once it is available.
+ EXPECT_EQ(expected.DebugString(), actual.DebugString());
+ }
+
+ // Parse the text and expect that the given errors are reported.
+ void ExpectHasErrors(const char* text, const char* expected_errors) {
+ ExpectHasEarlyExitErrors(text, expected_errors);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ }
+
+ // Same as above but does not expect that the parser parses the complete
+ // input.
+ void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) {
+ SetupParser(text);
+ FileDescriptorProto file;
+ parser_->Parse(input_.get(), &file);
+ EXPECT_EQ(expected_errors, error_collector_.text_);
+ }
+
+ // Parse the text as a file and validate it (with a DescriptorPool), and
+ // expect that the validation step reports the given errors.
+ void ExpectHasValidationErrors(const char* text,
+ const char* expected_errors) {
+ SetupParser(text);
+ SourceLocationTable source_locations;
+ parser_->RecordSourceLocationsTo(&source_locations);
+
+ FileDescriptorProto file;
+ file.set_name("foo.proto");
+ parser_->Parse(input_.get(), &file);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ MockValidationErrorCollector validation_error_collector(source_locations,
+ &error_collector_);
+ EXPECT_TRUE(pool_.BuildFileCollectingErrors(
+ file, &validation_error_collector) == NULL);
+ EXPECT_EQ(expected_errors, error_collector_.text_);
+ }
+
+ MockErrorCollector error_collector_;
+ DescriptorPool pool_;
+
+ std::unique_ptr<io::ZeroCopyInputStream> raw_input_;
+ std::unique_ptr<io::Tokenizer> input_;
+ std::unique_ptr<Parser> parser_;
+ bool require_syntax_identifier_;
+};
+
+// ===================================================================
+
+TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
+ SetupParser(
+ "// blah\n"
+ "syntax = \"foobar\";\n"
+ "this line will not be parsed\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("", error_collector_.text_);
+ EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
+ SetupParser(
+ "// blah\n"
+ "this line will not be parsed\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("", error_collector_.text_);
+ EXPECT_EQ("", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
+ SetupParser(
+ "// blah\n"
+ "syntax = error;\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_FALSE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
+}
+
+TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) {
+ SetupParser("message A {}");
+ FileDescriptorProto file;
+ CaptureTestStderr();
+ EXPECT_TRUE(parser_->Parse(input_.get(), &file));
+ EXPECT_TRUE(GetCapturedTestStderr().find("No syntax specified") !=
+ std::string::npos);
+}
+
+TEST_F(ParserTest, WarnIfFieldNameIsNotUpperCamel) {
+ SetupParser(
+ "syntax = \"proto2\";"
+ "message abc {}");
+ FileDescriptorProto file;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &file));
+ EXPECT_TRUE(error_collector_.warning_.find(
+ "Message name should be in UpperCamelCase. Found: abc.") !=
+ std::string::npos);
+}
+
+TEST_F(ParserTest, WarnIfFieldNameIsNotLowerUnderscore) {
+ SetupParser(
+ "syntax = \"proto2\";"
+ "message A {"
+ " optional string SongName = 1;"
+ "}");
+ FileDescriptorProto file;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &file));
+ EXPECT_TRUE(error_collector_.warning_.find(
+ "Field name should be lowercase. Found: SongName") !=
+ std::string::npos);
+}
+
+TEST_F(ParserTest, WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore) {
+ SetupParser(
+ "syntax = \"proto2\";"
+ "message A {"
+ " optional string song_name_1 = 1;"
+ "}");
+ FileDescriptorProto file;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &file));
+ EXPECT_TRUE(error_collector_.warning_.find(
+ "Number should not come right after an underscore. Found: "
+ "song_name_1.") != std::string::npos);
+}
+
+// ===================================================================
+
+typedef ParserTest ParseMessageTest;
+
+TEST_F(ParseMessageTest, IgnoreBOM) {
+ char input[] =
+ " message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n";
+ // Set UTF-8 BOM.
+ input[0] = (char)0xEF;
+ input[1] = (char)0xBB;
+ input[2] = (char)0xBF;
+ ExpectParsesTo(
+ input,
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, BOMError) {
+ char input[] =
+ " message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n";
+ input[0] = (char)0xEF;
+ ExpectHasErrors(input,
+ "0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
+ "Only UTF-8 is accepted for proto file.\n"
+ "0:0: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(ParseMessageTest, SimpleMessage) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
+ require_syntax_identifier_ = false;
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
+ ExpectParsesTo(
+ "syntax = \"proto2\";\n"
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n",
+
+ "syntax: 'proto2' "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
+ require_syntax_identifier_ = true;
+ ExpectParsesTo(
+ "syntax = \"proto2\";\n"
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ "}\n",
+
+ "syntax: 'proto2' "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ "}");
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseMessageTest, SimpleFields) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 15;\n"
+ " optional int32 bar = 34;\n"
+ " repeated int32 baz = 3;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }"
+ " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }"
+ " field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, PrimitiveFieldTypes) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ " required int64 foo = 1;\n"
+ " required uint32 foo = 1;\n"
+ " required uint64 foo = 1;\n"
+ " required sint32 foo = 1;\n"
+ " required sint64 foo = 1;\n"
+ " required fixed32 foo = 1;\n"
+ " required fixed64 foo = 1;\n"
+ " required sfixed32 foo = 1;\n"
+ " required sfixed64 foo = 1;\n"
+ " required float foo = 1;\n"
+ " required double foo = 1;\n"
+ " required string foo = 1;\n"
+ " required bytes foo = 1;\n"
+ " required bool foo = 1;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES number:1 "
+ "}"
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL number:1 "
+ "}"
+ "}");
+}
+
+TEST_F(ParseMessageTest, FieldDefaults) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1 [default= 1 ];\n"
+ " required int32 foo = 1 [default= -2 ];\n"
+ " required int64 foo = 1 [default= 3 ];\n"
+ " required int64 foo = 1 [default= -4 ];\n"
+ " required uint32 foo = 1 [default= 5 ];\n"
+ " required uint64 foo = 1 [default= 6 ];\n"
+ " required float foo = 1 [default= 7.5];\n"
+ " required float foo = 1 [default= -8.5];\n"
+ " required float foo = 1 [default= 9 ];\n"
+ " required double foo = 1 [default= 10.5];\n"
+ " required double foo = 1 [default=-11.5];\n"
+ " required double foo = 1 [default= 12 ];\n"
+ " required double foo = 1 [default= inf ];\n"
+ " required double foo = 1 [default=-inf ];\n"
+ " required double foo = 1 [default= nan ];\n"
+ " required string foo = 1 [default='13\\001'];\n"
+ " required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
+ " required bytes foo = 1 [default='14\\002'];\n"
+ " required bytes foo = 1 [default='a' \"b\" \n 'c'];\n"
+ " required bool foo = 1 [default=true ];\n"
+ " required Foo foo = 1 [default=FOO ];\n"
+
+ " required int32 foo = 1 [default= 0x7FFFFFFF];\n"
+ " required int32 foo = 1 [default=-0x80000000];\n"
+ " required uint32 foo = 1 [default= 0xFFFFFFFF];\n"
+ " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n"
+ " required int64 foo = 1 [default=-0x8000000000000000];\n"
+ " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n"
+ " required double foo = 1 [default= 0xabcd];\n"
+ "}\n",
+
+#define ETC "name:\"foo\" label:LABEL_REQUIRED number:1"
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { type:TYPE_INT32 default_value:\"1\" " ETC
+ " }"
+ " field { type:TYPE_INT32 default_value:\"-2\" " ETC
+ " }"
+ " field { type:TYPE_INT64 default_value:\"3\" " ETC
+ " }"
+ " field { type:TYPE_INT64 default_value:\"-4\" " ETC
+ " }"
+ " field { type:TYPE_UINT32 default_value:\"5\" " ETC
+ " }"
+ " field { type:TYPE_UINT64 default_value:\"6\" " ETC
+ " }"
+ " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC
+ " }"
+ " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC
+ " }"
+ " field { type:TYPE_FLOAT default_value:\"9\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"12\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC
+ " }"
+ " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC
+ " }"
+ " field { type:TYPE_STRING default_value:\"13\\001\" " ETC
+ " }"
+ " field { type:TYPE_STRING default_value:\"abc\" " ETC
+ " }"
+ " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC
+ " }"
+ " field { type:TYPE_BYTES default_value:\"abc\" " ETC
+ " }"
+ " field { type:TYPE_BOOL default_value:\"true\" " ETC
+ " }"
+ " field { type_name:\"Foo\" default_value:\"FOO\" " ETC
+ " }"
+
+ " field {"
+ " type:TYPE_INT32 default_value:\"2147483647\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT32 default_value:\"-2147483648\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT32 default_value:\"4294967295\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_DOUBLE default_value:\"43981\" " ETC
+ " }"
+ "}");
+#undef ETC
+}
+
+TEST_F(ParseMessageTest, FieldJsonName) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " optional string foo = 1 [json_name = \"@type\"];\n"
+ "}\n",
+ "message_type {"
+ " name: \"TestMessage\""
+ " field {\n"
+ " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
+ " json_name: \"@type\"\n"
+ " }\n"
+ "}\n");
+}
+
+TEST_F(ParseMessageTest, FieldOptions) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " optional string foo = 1\n"
+ " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n"
+ " (quux)=\"x\040y\", (baz.qux)=hey];\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: "
+ "1"
+ " options { uninterpreted_option: { name { name_part: \"ctype\" "
+ " is_extension: false "
+ "} "
+ " identifier_value: \"CORD\" "
+ "}"
+ " uninterpreted_option: { name { name_part: \"foo\" "
+ " is_extension: true } "
+ " positive_int_value: 7 }"
+ " uninterpreted_option: { name { name_part: \"foo\" "
+ " is_extension: false "
+ "} "
+ " name { name_part: "
+ "\".bar.baz\""
+ " is_extension: true } "
+ " name { name_part: \"qux\" "
+ " is_extension: false "
+ "} "
+ " name { name_part: \"quux\" "
+ " is_extension: false "
+ "} "
+ " name { name_part: \"corge\" "
+ " is_extension: true } "
+ " negative_int_value: -33 }"
+ " uninterpreted_option: { name { name_part: \"quux\" "
+ " is_extension: true } "
+ " string_value: \"x y\" }"
+ " uninterpreted_option: { name { name_part: "
+ "\"baz.qux\" "
+ " is_extension: true } "
+ " identifier_value: \"hey\" }"
+ " }"
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, Oneof) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " int32 a = 1;\n"
+ " string b = 2;\n"
+ " TestMessage c = 3;\n"
+ " group D = 4 { optional int32 i = 5; }\n"
+ " }\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+ " oneof_index:0 }"
+ " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
+ " oneof_index:0 }"
+ " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" "
+ " number:3 oneof_index:0 }"
+ " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP "
+ " type_name:\"D\" number:4 oneof_index:0 }"
+ " oneof_decl {"
+ " name: \"foo\""
+ " }"
+ " nested_type {"
+ " name: \"D\""
+ " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }"
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, MultipleOneofs) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " int32 a = 1;\n"
+ " string b = 2;\n"
+ " }\n"
+ " oneof bar {\n"
+ " int32 c = 3;\n"
+ " string d = 4;\n"
+ " }\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+ " oneof_index:0 }"
+ " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
+ " oneof_index:0 }"
+ " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 "
+ " oneof_index:1 }"
+ " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 "
+ " oneof_index:1 }"
+ " oneof_decl {"
+ " name: \"foo\""
+ " }"
+ " oneof_decl {"
+ " name: \"bar\""
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, Maps) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " map<int32, string> primitive_type_map = 1;\n"
+ " map<KeyType, ValueType> composite_type_map = 2;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " nested_type {"
+ " name: \"PrimitiveTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type:TYPE_INT32"
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type:TYPE_STRING"
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " nested_type {"
+ " name: \"CompositeTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type_name: \"KeyType\""
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type_name: \"ValueType\""
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " field {"
+ " name: \"primitive_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"PrimitiveTypeMapEntry\""
+ " number: 1"
+ " }"
+ " field {"
+ " name: \"composite_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"CompositeTypeMapEntry\""
+ " number: 2"
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, Group) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " optional group TestGroup = 1 {};\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " nested_type { name: \"TestGroup\" }"
+ " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1"
+ " type:TYPE_GROUP type_name: \"TestGroup\" }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, NestedMessage) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " message Nested {}\n"
+ " optional Nested test_nested = 1;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " nested_type { name: \"Nested\" }"
+ " field { name:\"test_nested\" label:LABEL_OPTIONAL number:1"
+ " type_name: \"Nested\" }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, NestedEnum) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " enum NestedEnum {}\n"
+ " optional NestedEnum test_enum = 1;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " enum_type { name: \"NestedEnum\" }"
+ " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1"
+ " type_name: \"NestedEnum\" }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ReservedRange) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ " reserved 2, 15, 9 to 11, 3, 20 to max;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ " reserved_range { start:2 end:3 }"
+ " reserved_range { start:15 end:16 }"
+ " reserved_range { start:9 end:12 }"
+ " reserved_range { start:3 end:4 }"
+ " reserved_range { start:20 end:536870912 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " option message_set_wire_format = true;\n"
+ " reserved 20 to max;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"message_set_wire_format\""
+ " is_extension: false"
+ " }"
+ " identifier_value: \"true\""
+ " }"
+ " }"
+ " reserved_range { start:20 end:2147483647 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ReservedNames) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}");
+}
+
+TEST_F(ParseMessageTest, ExtensionRange) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 10 to 19;\n"
+ " extensions 30 to max;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range { start:10 end:20 }"
+ " extension_range { start:30 end:536870912 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ExtensionRangeWithOptions) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 10 to 19 [(i) = 5];\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range {"
+ " start:10"
+ " end:20"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, CompoundExtensionRange) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 2, 15, 9 to 11, 100 to max, 3;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range { start:2 end:3 }"
+ " extension_range { start:15 end:16 }"
+ " extension_range { start:9 end:12 }"
+ " extension_range { start:100 end:536870912 }"
+ " extension_range { start:3 end:4 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range {"
+ " start:2"
+ " end:3"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ " extension_range {"
+ " start:15"
+ " end:16"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ " extension_range {"
+ " start:9"
+ " end:12"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ " extension_range {"
+ " start:100"
+ " end:536870912"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ " extension_range {"
+ " start:3"
+ " end:4"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: \"i\""
+ " is_extension: true"
+ " }"
+ " positive_int_value: 5"
+ " }"
+ " }"
+ " }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
+ // Messages using the message_set_wire_format option can accept larger
+ // extension numbers, as the numbers are not encoded as int32 field values
+ // rather than tags.
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 4 to max;\n"
+ " option message_set_wire_format = true;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range { start:4 end: 0x7fffffff }"
+ " options {\n"
+ " uninterpreted_option { \n"
+ " name {\n"
+ " name_part: \"message_set_wire_format\"\n"
+ " is_extension: false\n"
+ " }\n"
+ " identifier_value: \"true\"\n"
+ " }\n"
+ " }\n"
+ "}");
+}
+
+TEST_F(ParseMessageTest, Extensions) {
+ ExpectParsesTo(
+ "extend Extendee1 { optional int32 foo = 12; }\n"
+ "extend Extendee2 { repeated TestMessage bar = 22; }\n",
+
+ "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
+ " extendee: \"Extendee1\" } "
+ "extension { name:\"bar\" label:LABEL_REPEATED number:22"
+ " type_name:\"TestMessage\" extendee: \"Extendee2\" }");
+}
+
+TEST_F(ParseMessageTest, ExtensionsInMessageScope) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extend Extendee1 { optional int32 foo = 12; }\n"
+ " extend Extendee2 { repeated TestMessage bar = 22; }\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 "
+ "number:12"
+ " extendee: \"Extendee1\" }"
+ " extension { name:\"bar\" label:LABEL_REPEATED number:22"
+ " type_name:\"TestMessage\" extendee: \"Extendee2\" }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
+ ExpectParsesTo(
+ "extend Extendee1 {\n"
+ " optional int32 foo = 12;\n"
+ " repeated TestMessage bar = 22;\n"
+ "}\n",
+
+ "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
+ " extendee: \"Extendee1\" } "
+ "extension { name:\"bar\" label:LABEL_REPEATED number:22"
+ " type_name:\"TestMessage\" extendee: \"Extendee1\" }");
+}
+
+TEST_F(ParseMessageTest, OptionalLabelProto3) {
+ ExpectParsesTo(
+ "syntax = \"proto3\";\n"
+ "message TestMessage {\n"
+ " int32 foo = 1;\n"
+ "}\n",
+
+ "syntax: \"proto3\" "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } "
+ "}");
+}
+
+TEST_F(ParseMessageTest, ExplicitOptionalLabelProto3) {
+ ExpectParsesTo(
+ "syntax = 'proto3';\n"
+ "message TestMessage {\n"
+ " optional int32 foo = 1;\n"
+ "}\n",
+
+ "syntax: \"proto3\" "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+ " proto3_optional: true oneof_index: 0 } "
+ " oneof_decl { name:\"_foo\" } "
+ "}");
+
+ // Handle collisions in the synthetic oneof name.
+ ExpectParsesTo(
+ "syntax = 'proto3';\n"
+ "message TestMessage {\n"
+ " optional int32 foo = 1;\n"
+ " oneof _foo {\n"
+ " int32 __foo = 2;\n"
+ " }\n"
+ "}\n",
+
+ "syntax: \"proto3\" "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
+ " proto3_optional: true oneof_index: 1 } "
+ " field { name:\"__foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 "
+ " oneof_index: 0 } "
+ " oneof_decl { name:\"_foo\" } "
+ " oneof_decl { name:\"X_foo\" } "
+ "}");
+}
+
+// ===================================================================
+
+typedef ParserTest ParseEnumTest;
+
+TEST_F(ParseEnumTest, SimpleEnum) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 0;\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:0 }"
+ "}");
+}
+
+TEST_F(ParseEnumTest, Values) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 13;\n"
+ " BAR = -10;\n"
+ " BAZ = 500;\n"
+ " HEX_MAX = 0x7FFFFFFF;\n"
+ " HEX_MIN = -0x80000000;\n"
+ " INT_MAX = 2147483647;\n"
+ " INT_MIN = -2147483648;\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:13 }"
+ " value { name:\"BAR\" number:-10 }"
+ " value { name:\"BAZ\" number:500 }"
+ " value { name:\"HEX_MAX\" number:2147483647 }"
+ " value { name:\"HEX_MIN\" number:-2147483648 }"
+ " value { name:\"INT_MAX\" number:2147483647 }"
+ " value { name:\"INT_MIN\" number:-2147483648 }"
+ "}");
+}
+
+TEST_F(ParseEnumTest, ValueOptions) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 13;\n"
+ " BAR = -10 [ (something.text) = 'abc' ];\n"
+ " BAZ = 500 [ (something.text) = 'def', other = 1 ];\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name: \"FOO\" number: 13 }"
+ " value { name: \"BAR\" number: -10 "
+ " options { "
+ " uninterpreted_option { "
+ " name { name_part: \"something.text\" is_extension: true } "
+ " string_value: \"abc\" "
+ " } "
+ " } "
+ " } "
+ " value { name: \"BAZ\" number: 500 "
+ " options { "
+ " uninterpreted_option { "
+ " name { name_part: \"something.text\" is_extension: true } "
+ " string_value: \"def\" "
+ " } "
+ " uninterpreted_option { "
+ " name { name_part: \"other\" is_extension: false } "
+ " positive_int_value: 1 "
+ " } "
+ " } "
+ " } "
+ "}");
+}
+
+TEST_F(ParseEnumTest, ReservedRange) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 0;\n"
+ " reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to "
+ "max;\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:0 }"
+ " reserved_range { start:-2147483648 end:-2147483648 }"
+ " reserved_range { start:-6 end:-4 }"
+ " reserved_range { start:-1 end:1 }"
+ " reserved_range { start:2 end:2 }"
+ " reserved_range { start:15 end:15 }"
+ " reserved_range { start:9 end:11 }"
+ " reserved_range { start:3 end:3 }"
+ " reserved_range { start:20 end:2147483647 }"
+ "}");
+}
+
+TEST_F(ParseEnumTest, ReservedNames) {
+ ExpectParsesTo(
+ "enum TestEnum {\n"
+ " FOO = 0;\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n",
+
+ "enum_type {"
+ " name: \"TestEnum\""
+ " value { name:\"FOO\" number:0 }"
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}");
+}
+
+// ===================================================================
+
+typedef ParserTest ParseServiceTest;
+
+TEST_F(ParseServiceTest, SimpleService) {
+ ExpectParsesTo(
+ "service TestService {\n"
+ " rpc Foo(In) returns (Out);\n"
+ "}\n",
+
+ "service {"
+ " name: \"TestService\""
+ " method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }"
+ "}");
+}
+
+TEST_F(ParseServiceTest, MethodsAndStreams) {
+ ExpectParsesTo(
+ "service TestService {\n"
+ " rpc Foo(In1) returns (Out1);\n"
+ " rpc Bar(In2) returns (Out2);\n"
+ " rpc Baz(In3) returns (Out3);\n"
+ "}\n",
+
+ "service {"
+ " name: \"TestService\""
+ " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }"
+ " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }"
+ " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }"
+ "}");
+}
+
+
+// ===================================================================
+// imports and packages
+
+typedef ParserTest ParseMiscTest;
+
+TEST_F(ParseMiscTest, ParseImport) {
+ ExpectParsesTo("import \"foo/bar/baz.proto\";\n",
+ "dependency: \"foo/bar/baz.proto\"");
+}
+
+TEST_F(ParseMiscTest, ParseMultipleImports) {
+ ExpectParsesTo(
+ "import \"foo.proto\";\n"
+ "import \"bar.proto\";\n"
+ "import \"baz.proto\";\n",
+ "dependency: \"foo.proto\""
+ "dependency: \"bar.proto\""
+ "dependency: \"baz.proto\"");
+}
+
+TEST_F(ParseMiscTest, ParsePublicImports) {
+ ExpectParsesTo(
+ "import \"foo.proto\";\n"
+ "import public \"bar.proto\";\n"
+ "import \"baz.proto\";\n"
+ "import public \"qux.proto\";\n",
+ "dependency: \"foo.proto\""
+ "dependency: \"bar.proto\""
+ "dependency: \"baz.proto\""
+ "dependency: \"qux.proto\""
+ "public_dependency: 1 "
+ "public_dependency: 3 ");
+}
+
+TEST_F(ParseMiscTest, ParsePackage) {
+ ExpectParsesTo("package foo.bar.baz;\n", "package: \"foo.bar.baz\"");
+}
+
+TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
+ ExpectParsesTo(
+ "package foo . bar. \n"
+ " baz;\n",
+ "package: \"foo.bar.baz\"");
+}
+
+// ===================================================================
+// options
+
+TEST_F(ParseMiscTest, ParseFileOptions) {
+ ExpectParsesTo(
+ "option java_package = \"com.google.foo\";\n"
+ "option optimize_for = CODE_SIZE;",
+
+ "options {"
+ "uninterpreted_option { name { name_part: \"java_package\" "
+ " is_extension: false }"
+ " string_value: \"com.google.foo\"} "
+ "uninterpreted_option { name { name_part: \"optimize_for\" "
+ " is_extension: false }"
+ " identifier_value: \"CODE_SIZE\" } "
+ "}");
+}
+
+// ===================================================================
+// Error tests
+//
+// There are a very large number of possible errors that the parser could
+// report, so it's infeasible to test every single one of them. Instead,
+// we test each unique call to AddError() in parser.h. This does not mean
+// we are testing every possible error that Parser can generate because
+// each variant of the Consume() helper only counts as one unique call to
+// AddError().
+
+typedef ParserTest ParseErrorTest;
+
+TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
+ require_syntax_identifier_ = true;
+ ExpectHasEarlyExitErrors("message TestMessage {}",
+ "0:0: File must begin with a syntax statement, e.g. "
+ "'syntax = \"proto2\";'.\n");
+ EXPECT_EQ("", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
+ ExpectHasEarlyExitErrors(
+ "syntax = \"no_such_syntax\";",
+ "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser "
+ "only recognizes \"proto2\" and \"proto3\".\n");
+ EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, SimpleSyntaxError) {
+ ExpectHasErrors("message TestMessage @#$ { blah }",
+ "0:20: Expected \"{\".\n");
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParseErrorTest, ExpectedTopLevel) {
+ ExpectHasErrors("blah;",
+ "0:0: Expected top-level statement (e.g. \"message\").\n");
+}
+
+TEST_F(ParseErrorTest, UnmatchedCloseBrace) {
+ // This used to cause an infinite loop. Doh.
+ ExpectHasErrors("}",
+ "0:0: Expected top-level statement (e.g. \"message\").\n"
+ "0:0: Unmatched \"}\".\n");
+}
+
+// -------------------------------------------------------------------
+// Message errors
+
+TEST_F(ParseErrorTest, MessageMissingName) {
+ ExpectHasErrors("message {}", "0:8: Expected message name.\n");
+}
+
+TEST_F(ParseErrorTest, MessageMissingBody) {
+ ExpectHasErrors("message TestMessage;", "0:19: Expected \"{\".\n");
+}
+
+TEST_F(ParseErrorTest, EofInMessage) {
+ ExpectHasErrors(
+ "message TestMessage {",
+ "0:21: Reached end of input in message definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, MissingFieldNumber) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional int32 foo;\n"
+ "}\n",
+ "1:20: Missing field number.\n");
+}
+
+TEST_F(ParseErrorTest, ExpectedFieldNumber) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional int32 foo = ;\n"
+ "}\n",
+ "1:23: Expected field number.\n");
+}
+
+TEST_F(ParseErrorTest, FieldNumberOutOfRange) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional int32 foo = 0x100000000;\n"
+ "}\n",
+ "1:23: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, MissingLabel) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " int32 foo = 1;\n"
+ "}\n",
+ "1:2: Expected \"required\", \"optional\", or \"repeated\".\n");
+}
+
+TEST_F(ParseErrorTest, ExpectedOptionName) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [];\n"
+ "}\n",
+ "1:27: Expected identifier.\n");
+}
+
+TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [.foo=1];\n"
+ "}\n",
+ "1:27: Expected identifier.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [default=true];\n"
+ "}\n",
+ "1:35: Expected integer for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional bool foo = 1 [default=blah];\n"
+ "}\n",
+ "1:33: Expected \"true\" or \"false\".\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueNotString) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional string foo = 1 [default=1];\n"
+ "}\n",
+ "1:35: Expected string for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [default=-1];\n"
+ "}\n",
+ "1:36: Unsigned field can't have negative default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueTooLarge) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional int32 foo = 1 [default= 0x80000000];\n"
+ " optional int32 foo = 1 [default=-0x80000001];\n"
+ " optional uint32 foo = 1 [default= 0x100000000];\n"
+ " optional int64 foo = 1 [default= 0x80000000000000000];\n"
+ " optional int64 foo = 1 [default=-0x80000000000000001];\n"
+ " optional uint64 foo = 1 [default= 0x100000000000000000];\n"
+ "}\n",
+ "1:36: Integer out of range.\n"
+ "2:36: Integer out of range.\n"
+ "3:36: Integer out of range.\n"
+ "4:36: Integer out of range.\n"
+ "5:36: Integer out of range.\n"
+ "6:36: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, JsonNameNotString) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional string foo = 1 [json_name=1];\n"
+ "}\n",
+ "1:37: Expected string for JSON name.\n");
+}
+
+TEST_F(ParseErrorTest, DuplicateJsonName) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
+ "}\n",
+ "1:41: Already set option \"json_name\".\n");
+}
+
+TEST_F(ParseErrorTest, EnumValueOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " HEX_TOO_BIG = 0x80000000;\n"
+ " HEX_TOO_SMALL = -0x80000001;\n"
+ " INT_TOO_BIG = 2147483648;\n"
+ " INT_TOO_SMALL = -2147483649;\n"
+ "}\n",
+ "1:19: Integer out of range.\n"
+ "2:19: Integer out of range.\n"
+ "3:19: Integer out of range.\n"
+ "4:19: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumAllowAliasFalse) {
+ ExpectHasErrors(
+ "enum Foo {\n"
+ " option allow_alias = false;\n"
+ " BAR = 1;\n"
+ " BAZ = 2;\n"
+ "}\n",
+ "5:0: \"Foo\" declares 'option allow_alias = false;' which has no "
+ "effect. "
+ "Please remove the declaration.\n");
+}
+
+TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) {
+ ExpectHasErrors(
+ "enum Foo {\n"
+ " option allow_alias = true;\n"
+ " BAR = 1;\n"
+ " BAZ = 2;\n"
+ "}\n",
+ "5:0: \"Foo\" declares support for enum aliases but no enum values share "
+ "field numbers. Please remove the unnecessary 'option allow_alias = "
+ "true;' "
+ "declaration.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueMissing) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [default=];\n"
+ "}\n",
+ "1:35: Expected integer for field default value.\n");
+}
+
+TEST_F(ParseErrorTest, DefaultValueForGroup) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional group Foo = 1 [default=blah] {}\n"
+ "}\n",
+ "1:34: Messages can't have default values.\n");
+}
+
+TEST_F(ParseErrorTest, DuplicateDefaultValue) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional uint32 foo = 1 [default=1,default=2];\n"
+ "}\n",
+ "1:37: Already set option \"default\".\n");
+}
+
+TEST_F(ParseErrorTest, MissingOneofName) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " oneof {\n"
+ " int32 bar = 1;\n"
+ " }\n"
+ "}\n",
+ "1:8: Expected oneof name.\n");
+}
+
+TEST_F(ParseErrorTest, LabelInOneof) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " optional int32 bar = 1;\n"
+ " }\n"
+ "}\n",
+ "2:4: Fields in oneofs must not have labels (required / optional "
+ "/ repeated).\n");
+}
+
+TEST_F(ParseErrorTest, MapInOneof) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " map<int32, int32> foo_map = 1;\n"
+ " map message_field = 2;\n" // a normal message field is OK
+ " }\n"
+ "}\n",
+ "2:7: Map fields are not allowed in oneofs.\n");
+}
+
+TEST_F(ParseErrorTest, LabelForMap) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional map<int32, int32> int_map = 1;\n"
+ " required map<int32, int32> int_map2 = 2;\n"
+ " repeated map<int32, int32> int_map3 = 3;\n"
+ " optional map map_message = 4;\n" // a normal message field is OK
+ "}\n",
+ "1:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "2:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "3:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n");
+}
+
+TEST_F(ParseErrorTest, MalformedMaps) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " map map_message = 1;\n" // a normal message field lacking label
+ " map<string> str_map = 2;\n"
+ " map<string,> str_map2 = 3;\n"
+ " map<,string> str_map3 = 4;\n"
+ " map<> empty_map = 5;\n"
+ " map<string,string str_map6 = 6;\n"
+ "}"
+ "extend SomeMessage {\n"
+ " map<int32, int32> int_map = 1;\n"
+ "}",
+ "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
+ "2:12: Expected \",\".\n"
+ "3:13: Expected type name.\n"
+ "4:6: Expected type name.\n"
+ "5:6: Expected type name.\n"
+ "6:20: Expected \">\".\n"
+ "8:5: Map fields are not allowed to be extensions.\n");
+}
+
+TEST_F(ParseErrorTest, GroupNotCapitalized) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional group foo = 1 {}\n"
+ "}\n",
+ "1:17: Group names must start with a capital letter.\n");
+}
+
+TEST_F(ParseErrorTest, GroupMissingBody) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional group Foo = 1;\n"
+ "}\n",
+ "1:24: Missing group body.\n");
+}
+
+TEST_F(ParseErrorTest, ExtendingPrimitive) {
+ ExpectHasErrors("extend int32 { optional string foo = 4; }\n",
+ "0:7: Expected message type.\n");
+}
+
+TEST_F(ParseErrorTest, ErrorInExtension) {
+ ExpectHasErrors(
+ "message Foo { extensions 100 to 199; }\n"
+ "extend Foo { optional string foo; }\n",
+ "1:32: Missing field number.\n");
+}
+
+TEST_F(ParseErrorTest, MultipleParseErrors) {
+ // When a statement has a parse error, the parser should be able to continue
+ // parsing at the next statement.
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional int32 foo;\n"
+ " !invalid statement ending in a block { blah blah { blah } blah }\n"
+ " optional int32 bar = 3 {}\n"
+ "}\n",
+ "1:20: Missing field number.\n"
+ "2:2: Expected \"required\", \"optional\", or \"repeated\".\n"
+ "2:2: Expected type name.\n"
+ "3:25: Expected \";\".\n");
+}
+
+TEST_F(ParseErrorTest, EofInAggregateValue) {
+ ExpectHasErrors(
+ "option (fileopt) = { i:100\n",
+ "1:0: Unexpected end of stream while parsing aggregate value.\n");
+}
+
+// -------------------------------------------------------------------
+// Enum errors
+
+TEST_F(ParseErrorTest, EofInEnum) {
+ ExpectHasErrors(
+ "enum TestEnum {",
+ "0:15: Reached end of input in enum definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, EnumValueMissingNumber) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO;\n"
+ "}\n",
+ "1:5: Missing numeric value for enum constant.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved max;\n"
+ "}\n",
+ "2:11: Expected enum value or number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved 10, \"foo\";\n"
+ "}\n",
+ "2:15: Expected enum number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ "FOO = 1;\n"
+ " reserved 2147483648;\n"
+ "}\n",
+ "2:11: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ "FOO = 1;\n"
+ " reserved -2147483649;\n"
+ "}\n",
+ "2:12: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMissingQuotes) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " FOO = 1;\n"
+ " reserved foo;\n"
+ "}\n",
+ "2:11: Expected enum value or number range.\n");
+}
+
+// -------------------------------------------------------------------
+// Reserved field number errors
+
+TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved max;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 10, \"foo\";\n"
+ "}\n",
+ "1:15: Expected field number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMissingQuotes) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved foo;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedNegativeNumber) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved -10;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedNumberOutOfRange) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 2147483648;\n"
+ "}\n",
+ "1:11: Integer out of range.\n");
+}
+
+// -------------------------------------------------------------------
+// Service errors
+
+TEST_F(ParseErrorTest, EofInService) {
+ ExpectHasErrors(
+ "service TestService {",
+ "0:21: Reached end of input in service definition (missing '}').\n");
+}
+
+TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
+ ExpectHasErrors(
+ "service TestService {\n"
+ " rpc Foo(int32) returns (string);\n"
+ "}\n",
+ "1:10: Expected message type.\n"
+ "1:26: Expected message type.\n");
+}
+
+
+TEST_F(ParseErrorTest, EofInMethodOptions) {
+ ExpectHasErrors(
+ "service TestService {\n"
+ " rpc Foo(Bar) returns(Bar) {",
+ "1:29: Reached end of input in method options (missing '}').\n"
+ "1:29: Reached end of input in service definition (missing '}').\n");
+}
+
+
+TEST_F(ParseErrorTest, PrimitiveMethodInput) {
+ ExpectHasErrors(
+ "service TestService {\n"
+ " rpc Foo(int32) returns(Bar);\n"
+ "}\n",
+ "1:10: Expected message type.\n");
+}
+
+
+TEST_F(ParseErrorTest, MethodOptionTypeError) {
+ // This used to cause an infinite loop.
+ ExpectHasErrors(
+ "message Baz {}\n"
+ "service Foo {\n"
+ " rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n"
+ "}\n",
+ "2:45: Expected \"=\".\n");
+}
+
+
+// -------------------------------------------------------------------
+// Import and package errors
+
+TEST_F(ParseErrorTest, ImportNotQuoted) {
+ ExpectHasErrors("import foo;\n",
+ "0:7: Expected a string naming the file to import.\n");
+}
+
+TEST_F(ParseErrorTest, MultiplePackagesInFile) {
+ ExpectHasErrors(
+ "package foo;\n"
+ "package bar;\n",
+ "1:0: Multiple package definitions.\n");
+}
+
+// ===================================================================
+// Test that errors detected by DescriptorPool correctly report line and
+// column numbers. We have one test for every call to RecordLocation() in
+// parser.cc.
+
+typedef ParserTest ParserValidationErrorTest;
+
+TEST_F(ParserValidationErrorTest, PackageNameError) {
+ // Create another file which defines symbol "foo".
+ FileDescriptorProto other_file;
+ other_file.set_name("bar.proto");
+ other_file.add_message_type()->set_name("foo");
+ EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+ // Now try to define it as a package.
+ ExpectHasValidationErrors(
+ "package foo.bar;",
+ "0:0: \"foo\" is already defined (as something other than a package) "
+ "in file \"bar.proto\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, ImportUnloadedError) {
+ ExpectHasValidationErrors(
+ "package test;\n"
+ "\n"
+ "import \"unloaded.proto\";",
+ "2:0: Import \"unloaded.proto\" has not been loaded.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ImportTwice) {
+ FileDescriptorProto other_file;
+ other_file.set_name("bar.proto");
+ other_file.add_message_type()->set_name("foo");
+ EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
+
+ ExpectHasValidationErrors(
+ "package test;\n"
+ "\n"
+ "import \"bar.proto\";\n"
+ " import \"bar.proto\";",
+ "3:2: Import \"bar.proto\" was listed twice.\n");
+}
+
+TEST_F(ParserValidationErrorTest, DuplicateFileError) {
+ FileDescriptorProto other_file;
+ other_file.set_name("foo.proto");
+ EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
+
+ ExpectHasValidationErrors(
+ "package test;", "0:0: A file with this name is already in the pool.\n");
+}
+
+TEST_F(ParserValidationErrorTest, MessageNameError) {
+ ExpectHasValidationErrors(
+ "message Foo {}\n"
+ "message Foo {}\n",
+ "1:8: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldNameError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " optional int32 bar = 1;\n"
+ " optional int32 bar = 2;\n"
+ "}\n",
+ "2:17: \"bar\" is already defined in \"Foo\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldTypeError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " optional Baz bar = 1;\n"
+ "}\n",
+ "1:11: \"Baz\" is not defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldNumberError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " optional int32 bar = 0;\n"
+ "}\n",
+ "1:23: Field numbers must be positive integers.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
+ ExpectHasValidationErrors("extend Baz { optional int32 bar = 1; }\n",
+ "0:7: \"Baz\" is not defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ExtensionJsonNameError) {
+ ExpectHasValidationErrors(
+ "message TestMessage {\n"
+ " extensions 1 to 100;\n"
+ "}\n"
+ "extend TestMessage {\n"
+ " optional int32 foo = 12 [json_name = \"bar\"];\n"
+ "}",
+ "4:27: option json_name is not allowed on extension fields.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldDefaultValueError) {
+ ExpectHasValidationErrors(
+ "enum Baz { QUX = 1; }\n"
+ "message Foo {\n"
+ " optional Baz bar = 1 [default=NO_SUCH_VALUE];\n"
+ "}\n",
+ "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FileOptionNameError) {
+ ExpectHasValidationErrors(
+ "option foo = 5;",
+ "0:7: Option \"foo\" unknown. Ensure that your proto definition file "
+ "imports the proto which defines the option.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FileOptionValueError) {
+ ExpectHasValidationErrors(
+ "option java_outer_classname = 5;",
+ "0:30: Value must be quoted string for string option "
+ "\"google.protobuf.FileOptions.java_outer_classname\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldOptionNameError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " optional bool bar = 1 [foo=1];\n"
+ "}\n",
+ "1:25: Option \"foo\" unknown. Ensure that your proto definition file "
+ "imports the proto which defines the option.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldOptionValueError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " optional int32 bar = 1 [ctype=1];\n"
+ "}\n",
+ "1:32: Value must be identifier for enum-valued option "
+ "\"google.protobuf.FieldOptions.ctype\".\n");
+}
+
+TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " extensions 0;\n"
+ "}\n",
+ "1:13: Extension numbers must be positive integers.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3ExtensionError) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "message Foo { \n"
+ " extensions 100 to 199;\n"
+ "}\n"
+ "extend Foo { string foo = 101; }\n",
+ "4:7: Extensions in proto3 are only allowed for defining options.\n"
+ "2:13: Extension ranges are not allowed in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3MessageSet) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "message Foo { \n"
+ " option message_set_wire_format = true;\n"
+ "}\n",
+ "1:8: MessageSet is not supported in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3Required) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "message Foo { \n"
+ " required int32 field = 1;"
+ "}\n",
+ "2:11: Required fields are not allowed in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3Default) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "message Foo { \n"
+ " int32 field = 1 [default = 12];"
+ "}\n",
+ "2:29: Explicit default values are not allowed in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3JsonConflictError) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "message TestMessage {\n"
+ " uint32 foo = 1;\n"
+ " uint32 Foo = 2;\n"
+ "}\n",
+ "3:9: The JSON camel-case name of field \"Foo\" conflicts with field "
+ "\"foo\". This is not allowed in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, EnumNameError) {
+ ExpectHasValidationErrors(
+ "enum Foo {A = 1;}\n"
+ "enum Foo {B = 1;}\n",
+ "1:5: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, Proto3EnumError) {
+ ExpectHasValidationErrors(
+ "syntax = 'proto3';\n"
+ "enum Foo {A = 1;}\n",
+ "1:14: The first enum value must be zero in proto3.\n");
+}
+
+TEST_F(ParserValidationErrorTest, EnumValueNameError) {
+ ExpectHasValidationErrors(
+ "enum Foo {\n"
+ " BAR = 1;\n"
+ " BAR = 1;\n"
+ "}\n",
+ "2:2: \"BAR\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, EnumValueAliasError) {
+ ExpectHasValidationErrors(
+ "enum Foo {\n"
+ " BAR = 1;\n"
+ " BAZ = 1;\n"
+ "}\n",
+ "2:8: \"BAZ\" uses the same enum value as \"BAR\". If this is "
+ "intended, set 'option allow_alias = true;' to the enum "
+ "definition.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ExplicitlyMapEntryError) {
+ ExpectHasValidationErrors(
+ "message Foo {\n"
+ " message ValueEntry {\n"
+ " option map_entry = true;\n"
+ " optional int32 key = 1;\n"
+ " optional int32 value = 2;\n"
+ " extensions 99 to 999;\n"
+ " }\n"
+ " repeated ValueEntry value = 1;\n"
+ "}",
+ "7:11: map_entry should not be set explicitly. Use "
+ "map<KeyType, ValueType> instead.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ServiceNameError) {
+ ExpectHasValidationErrors(
+ "service Foo {}\n"
+ "service Foo {}\n",
+ "1:8: \"Foo\" is already defined.\n");
+}
+
+TEST_F(ParserValidationErrorTest, MethodNameError) {
+ ExpectHasValidationErrors(
+ "message Baz {}\n"
+ "service Foo {\n"
+ " rpc Bar(Baz) returns(Baz);\n"
+ " rpc Bar(Baz) returns(Baz);\n"
+ "}\n",
+ "3:6: \"Bar\" is already defined in \"Foo\".\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
+ ExpectHasValidationErrors(
+ "message Baz {}\n"
+ "service Foo {\n"
+ " rpc Bar(Qux) returns(Baz);\n"
+ "}\n",
+ "2:10: \"Qux\" is not defined.\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
+ ExpectHasValidationErrors(
+ "message Baz {}\n"
+ "service Foo {\n"
+ " rpc Bar(Baz) returns(Qux);\n"
+ "}\n",
+ "2:23: \"Qux\" is not defined.\n");
+}
+
+
+TEST_F(ParserValidationErrorTest, ResolvedUndefinedError) {
+ // Create another file which defines symbol ".base.bar".
+ FileDescriptorProto other_file;
+ other_file.set_name("base.proto");
+ other_file.set_package("base");
+ other_file.add_message_type()->set_name("bar");
+ EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+ // Define "foo.base" and try "base.bar".
+ // "base.bar" is resolved to "foo.base.bar" which is not defined.
+ ExpectHasValidationErrors(
+ "package foo.base;\n"
+ "import \"base.proto\";\n"
+ "message qux {\n"
+ " optional base.bar baz = 1;\n"
+ " optional .base.bar quz = 2;\n"
+ "}\n",
+ "3:11: \"base.bar\" is resolved to \"foo.base.bar\","
+ " which is not defined. The innermost scope is searched first "
+ "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")"
+ " to start from the outermost scope.\n");
+}
+
+TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
+ // Build descriptor message in test pool
+ FileDescriptorProto descriptor_proto;
+ DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto);
+ ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL);
+
+ // base2.proto:
+ // package baz
+ // import net/proto2/proto/descriptor.proto
+ // message Bar { optional int32 foo = 1; }
+ // extend FileOptions { optional Bar bar = 7672757; }
+ FileDescriptorProto other_file;
+ other_file.set_name("base2.proto");
+ other_file.set_package("baz");
+ other_file.add_dependency();
+ other_file.set_dependency(0, descriptor_proto.name());
+
+ DescriptorProto* message(other_file.add_message_type());
+ message->set_name("Bar");
+ FieldDescriptorProto* field(message->add_field());
+ field->set_name("foo");
+ field->set_number(1);
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_type(FieldDescriptorProto::TYPE_INT32);
+
+ FieldDescriptorProto* extension(other_file.add_extension());
+ extension->set_name("bar");
+ extension->set_number(7672757);
+ extension->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ extension->set_type(FieldDescriptorProto::TYPE_MESSAGE);
+ extension->set_type_name("Bar");
+ extension->set_extendee("google.protobuf.FileOptions");
+
+ EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
+
+ // qux.proto:
+ // package qux.baz
+ // option (baz.bar).foo = 1;
+ //
+ // Although "baz.bar" is already defined, the lookup code will try
+ // "qux.baz.bar", since it's the match from the innermost scope,
+ // which will cause a symbol not defined error.
+ ExpectHasValidationErrors(
+ "package qux.baz;\n"
+ "import \"base2.proto\";\n"
+ "option (baz.bar).foo = 1;\n",
+ "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\","
+ " which is not defined. The innermost scope is searched first "
+ "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")"
+ " to start from the outermost scope.\n");
+}
+
+// ===================================================================
+// Test that the output from FileDescriptor::DebugString() (and all other
+// descriptor types) is parseable, and results in the same Descriptor
+// definitions again afoter parsing (note, however, that the order of messages
+// cannot be guaranteed to be the same)
+
+typedef ParserTest ParseDescriptorDebugTest;
+
+class CompareDescriptorNames {
+ public:
+ bool operator()(const DescriptorProto* left,
+ const DescriptorProto* right) const {
+ return left->name() < right->name();
+ }
+};
+
+// Sorts nested DescriptorProtos of a DescriptoProto, by name.
+void SortMessages(DescriptorProto* descriptor_proto) {
+ int size = descriptor_proto->nested_type_size();
+ // recursively sort; we can't guarantee the order of nested messages either
+ for (int i = 0; i < size; ++i) {
+ SortMessages(descriptor_proto->mutable_nested_type(i));
+ }
+ DescriptorProto** data =
+ descriptor_proto->mutable_nested_type()->mutable_data();
+ std::sort(data, data + size, CompareDescriptorNames());
+}
+
+// Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
+void SortMessages(FileDescriptorProto* file_descriptor_proto) {
+ int size = file_descriptor_proto->message_type_size();
+ // recursively sort; we can't guarantee the order of nested messages either
+ for (int i = 0; i < size; ++i) {
+ SortMessages(file_descriptor_proto->mutable_message_type(i));
+ }
+ DescriptorProto** data =
+ file_descriptor_proto->mutable_message_type()->mutable_data();
+ std::sort(data, data + size, CompareDescriptorNames());
+}
+
+// Strips the message and enum field type names for comparison purpose only.
+void StripFieldTypeName(DescriptorProto* proto) {
+ for (int i = 0; i < proto->field_size(); ++i) {
+ std::string type_name = proto->field(i).type_name();
+ std::string::size_type pos = type_name.find_last_of('.');
+ if (pos != std::string::npos) {
+ proto->mutable_field(i)->mutable_type_name()->assign(
+ type_name.begin() + pos + 1, type_name.end());
+ }
+ }
+ for (int i = 0; i < proto->nested_type_size(); ++i) {
+ StripFieldTypeName(proto->mutable_nested_type(i));
+ }
+}
+
+void StripFieldTypeName(FileDescriptorProto* file_proto) {
+ for (int i = 0; i < file_proto->message_type_size(); ++i) {
+ StripFieldTypeName(file_proto->mutable_message_type(i));
+ }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
+ const FileDescriptor* original_file =
+ protobuf_unittest::TestAllTypes::descriptor()->file();
+ FileDescriptorProto expected;
+ original_file->CopyTo(&expected);
+
+ // Get the DebugString of the unittest.proto FileDecriptor, which includes
+ // all other descriptor types
+ std::string debug_string = original_file->DebugString();
+
+ // Parse the debug string
+ SetupParser(debug_string.c_str());
+ FileDescriptorProto parsed;
+ parser_->Parse(input_.get(), &parsed);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" << debug_string;
+
+ // We now have a FileDescriptorProto, but to compare with the expected we
+ // need to link to a FileDecriptor, then output back to a proto. We'll
+ // also need to give it the same name as the original.
+ parsed.set_name(
+ TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+ // We need the imported dependency before we can build our parsed proto
+ const FileDescriptor* public_import =
+ protobuf_unittest_import::PublicImportMessage::descriptor()->file();
+ FileDescriptorProto public_import_proto;
+ public_import->CopyTo(&public_import_proto);
+ ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
+ const FileDescriptor* import =
+ protobuf_unittest_import::ImportMessage::descriptor()->file();
+ FileDescriptorProto import_proto;
+ import->CopyTo(&import_proto);
+ ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+ const FileDescriptor* actual = pool_.BuildFile(parsed);
+ parsed.Clear();
+ ASSERT_TRUE(actual != NULL) << "Failed to validate:\n" << debug_string;
+ actual->CopyTo(&parsed);
+ ASSERT_TRUE(actual != NULL);
+
+ // The messages might be in different orders, making them hard to compare.
+ // So, sort the messages in the descriptor protos (including nested messages,
+ // recursively).
+ SortMessages(&expected);
+ SortMessages(&parsed);
+
+ // I really wanted to use StringDiff here for the debug output on fail,
+ // but the strings are too long for it, and if I increase its max size,
+ // we get a memory allocation failure :(
+ EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
+TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
+ const FileDescriptor* original_file =
+ protobuf_unittest::AggregateMessage::descriptor()->file();
+ FileDescriptorProto expected;
+ original_file->CopyTo(&expected);
+
+ std::string debug_string = original_file->DebugString();
+
+ // Parse the debug string
+ SetupParser(debug_string.c_str());
+ FileDescriptorProto parsed;
+ parser_->Parse(input_.get(), &parsed);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We now have a FileDescriptorProto, but to compare with the expected we
+ // need to link to a FileDecriptor, then output back to a proto. We'll
+ // also need to give it the same name as the original.
+ parsed.set_name(original_file->name());
+
+ // unittest_custom_options.proto depends on descriptor.proto.
+ const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
+ FileDescriptorProto import_proto;
+ import->CopyTo(&import_proto);
+ ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+
+ FileDescriptorProto any_import;
+ google::protobuf::Any::descriptor()->file()->CopyTo(&any_import);
+ ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr);
+
+ const FileDescriptor* actual = pool_.BuildFile(parsed);
+ ASSERT_TRUE(actual != NULL);
+ parsed.Clear();
+ actual->CopyTo(&parsed);
+
+ // The messages might be in different orders, making them hard to compare.
+ // So, sort the messages in the descriptor protos (including nested messages,
+ // recursively).
+ SortMessages(&expected);
+ SortMessages(&parsed);
+
+ EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
+// Ensure that DebugStringWithOptions(), with |include_comments| set to true,
+// includes comments from the original parser input in all of the appropriate
+// places.
+TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
+ SetupParser(
+ "// Detached comment before syntax.\n"
+ "\n"
+ "// Syntax comment.\n"
+ "syntax = \"proto2\";\n"
+ "\n"
+ "// Detached comment before package.\n"
+ "\n"
+ "// Package comment.\n"
+ "package comment_test;\n"
+ "\n"
+ "// Detached comment before TestMessage1.\n"
+ "\n"
+ "// Message comment.\n"
+ "//\n"
+ "// More detail in message comment.\n"
+ "message TestMessage1 {\n"
+ "\n"
+ " // Detached comment before foo.\n"
+ "\n"
+ " // Field comment.\n"
+ " optional int32 foo = 1;\n"
+ "\n"
+ " // Detached comment before NestedMessage.\n"
+ "\n"
+ " // Nested-message comment.\n"
+ " message NestedMessage {\n"
+ " optional int32 bar = 1;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "// Detached comment before MyEnumType.\n"
+ "\n"
+ "// Enum comment.\n"
+ "enum MyEnumType {\n"
+ "\n"
+ " // Detached comment before ASDF.\n"
+ "\n"
+ " // Enum-value comment.\n"
+ " ASDF = 1;\n"
+ "}\n"
+ "\n"
+ "// Detached comment before MyService.\n"
+ "\n"
+ "// Service comment.\n"
+ "service MyService {\n"
+ "\n"
+ " // Detached comment before MyRPCCall.\n"
+ "\n"
+ " // RPC comment.\n"
+ " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
+ "}\n");
+
+ FileDescriptorProto parsed_desc;
+ parsed_desc.set_name("foo.proto");
+ SourceLocationTable source_locations;
+ parser_->RecordSourceLocationsTo(&source_locations);
+ parser_->Parse(input_.get(), &parsed_desc);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We need to import the FileDescriptorProto to get a FileDescriptor.
+ MockValidationErrorCollector collector(source_locations, &error_collector_);
+ const FileDescriptor* descriptor =
+ pool_.BuildFileCollectingErrors(parsed_desc, &collector);
+ ASSERT_TRUE(descriptor != NULL);
+
+ // Ensure that each of the comments appears somewhere in the DebugString().
+ // We don't test the exact comment placement or formatting, because we do not
+ // want to be too fragile here.
+ const char* expected_comments[] = {
+ "Detached comment before syntax.",
+ "Syntax comment.",
+ "Detached comment before package.",
+ "Package comment.",
+ "Detached comment before TestMessage1.",
+ "Message comment.",
+ "More detail in message comment.",
+ "Detached comment before foo.",
+ "Field comment",
+ "Detached comment before NestedMessage.",
+ "Nested-message comment",
+ "Detached comment before MyEnumType.",
+ "Enum comment",
+ "Detached comment before ASDF.",
+ "Enum-value comment",
+ "Detached comment before MyService.",
+ "Service comment",
+ "Detached comment before MyRPCCall.",
+ "RPC comment",
+ };
+
+ DebugStringOptions debug_string_options;
+ debug_string_options.include_comments = true;
+
+ {
+ const std::string debug_string =
+ descriptor->DebugStringWithOptions(debug_string_options);
+
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
+ std::string::size_type found_pos =
+ debug_string.find(expected_comments[i]);
+ EXPECT_TRUE(found_pos != std::string::npos)
+ << "\"" << expected_comments[i] << "\" not found.";
+ }
+
+ // Result of DebugStringWithOptions should be parseable.
+ SetupParser(debug_string.c_str());
+ FileDescriptorProto parsed;
+ parser_->Parse(input_.get(), &parsed);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n"
+ << debug_string;
+ }
+
+}
+
+TEST_F(ParseDescriptorDebugTest, TestMaps) {
+ SetupParser(
+ "syntax = \"proto3\"; "
+ "message Foo { "
+ " message Bar { } "
+ " map<int32, Bar> enum_message_map = 1; "
+ " map<string, float> primitive_map = 2; "
+ "} ");
+ FileDescriptorProto original;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &original));
+ original.set_name("foo.proto");
+ const FileDescriptor* file = pool_.BuildFile(original);
+ ASSERT_TRUE(file != NULL);
+
+ // Make sure the debug string uses map syntax and does not have the auto
+ // generated entry.
+ std::string debug_string = file->DebugString();
+ EXPECT_TRUE(debug_string.find("map<") != std::string::npos);
+ EXPECT_TRUE(debug_string.find("option map_entry") == std::string::npos);
+ EXPECT_TRUE(debug_string.find("MapEntry") == std::string::npos);
+
+ // Make sure the descriptor debug string is parsable.
+ FileDescriptorProto parsed;
+ SetupParser(debug_string.c_str());
+ parsed.set_name("foo.proto");
+ ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
+
+ original.clear_source_code_info();
+ parsed.clear_source_code_info();
+ StripFieldTypeName(&original);
+ StripFieldTypeName(&parsed);
+ EXPECT_EQ(original.DebugString(), parsed.DebugString());
+}
+
+// ===================================================================
+// SourceCodeInfo tests.
+
+// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
+// message to a particular sub-field.
+// * If the target is itself a message, sets *output_message to point at it,
+// *output_field to NULL, and *output_index to -1.
+// * Otherwise, if the target is an element of a repeated field, sets
+// *output_message to the containing message, *output_field to the descriptor
+// of the field, and *output_index to the index of the element.
+// * Otherwise, the target is a field (possibly a repeated field, but not any
+// one element). Sets *output_message to the containing message,
+// *output_field to the descriptor of the field, and *output_index to -1.
+// Returns true if the path was valid, false otherwise. A gTest failure is
+// recorded before returning false.
+bool FollowPath(const Message& root, const int* path_begin, const int* path_end,
+ const Message** output_message,
+ const FieldDescriptor** output_field, int* output_index) {
+ if (path_begin == path_end) {
+ // Path refers to this whole message.
+ *output_message = &root;
+ *output_field = NULL;
+ *output_index = -1;
+ return true;
+ }
+
+ const Descriptor* descriptor = root.GetDescriptor();
+ const Reflection* reflection = root.GetReflection();
+
+ const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
+
+ if (field == NULL) {
+ ADD_FAILURE() << descriptor->name()
+ << " has no field number: " << *path_begin;
+ return false;
+ }
+
+ ++path_begin;
+
+ if (field->is_repeated()) {
+ if (path_begin == path_end) {
+ // Path refers to the whole repeated field.
+ *output_message = &root;
+ *output_field = field;
+ *output_index = -1;
+ return true;
+ }
+
+ int index = *path_begin++;
+ int size = reflection->FieldSize(root, field);
+
+ if (index >= size) {
+ ADD_FAILURE() << descriptor->name() << "." << field->name()
+ << " has size " << size
+ << ", but path contained index: " << index;
+ return false;
+ }
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Descend into child message.
+ const Message& child = reflection->GetRepeatedMessage(root, field, index);
+ return FollowPath(child, path_begin, path_end, output_message,
+ output_field, output_index);
+ } else if (path_begin == path_end) {
+ // Path refers to this element.
+ *output_message = &root;
+ *output_field = field;
+ *output_index = index;
+ return true;
+ } else {
+ ADD_FAILURE() << descriptor->name() << "." << field->name()
+ << " is not a message; cannot descend into it.";
+ return false;
+ }
+ } else {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ const Message& child = reflection->GetMessage(root, field);
+ return FollowPath(child, path_begin, path_end, output_message,
+ output_field, output_index);
+ } else if (path_begin == path_end) {
+ // Path refers to this field.
+ *output_message = &root;
+ *output_field = field;
+ *output_index = -1;
+ return true;
+ } else {
+ ADD_FAILURE() << descriptor->name() << "." << field->name()
+ << " is not a message; cannot descend into it.";
+ return false;
+ }
+ }
+}
+
+// Check if two spans are equal.
+bool CompareSpans(const RepeatedField<int>& span1,
+ const RepeatedField<int>& span2) {
+ if (span1.size() != span2.size()) return false;
+ for (int i = 0; i < span1.size(); i++) {
+ if (span1.Get(i) != span2.Get(i)) return false;
+ }
+ return true;
+}
+
+// Test fixture for source info tests, which check that source locations are
+// recorded correctly in FileDescriptorProto.source_code_info.location.
+class SourceInfoTest : public ParserTest {
+ protected:
+ // The parsed file (initialized by Parse()).
+ FileDescriptorProto file_;
+
+ // Parse the given text as a .proto file and populate the spans_ map with
+ // all the source location spans in its SourceCodeInfo table.
+ bool Parse(const char* text) {
+ ExtractMarkers(text);
+ SetupParser(text_without_markers_.c_str());
+ if (!parser_->Parse(input_.get(), &file_)) {
+ return false;
+ }
+
+ const SourceCodeInfo& source_info = file_.source_code_info();
+ for (int i = 0; i < source_info.location_size(); i++) {
+ const SourceCodeInfo::Location& location = source_info.location(i);
+ const Message* descriptor_proto = NULL;
+ const FieldDescriptor* field = NULL;
+ int index = 0;
+ if (!FollowPath(file_, location.path().begin(), location.path().end(),
+ &descriptor_proto, &field, &index)) {
+ return false;
+ }
+
+ spans_.insert(
+ std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
+ }
+
+ return true;
+ }
+
+ void TearDown() override {
+ EXPECT_TRUE(spans_.empty()) << "Forgot to call HasSpan() for:\n"
+ << spans_.begin()->second->DebugString();
+ }
+
+ // -----------------------------------------------------------------
+ // HasSpan() checks that the span of source code delimited by the given
+ // tags (comments) correspond via the SourceCodeInfo table to the given
+ // part of the FileDescriptorProto. (If unclear, look at the actual tests;
+ // it should quickly become obvious.)
+
+ bool HasSpan(char start_marker, char end_marker,
+ const Message& descriptor_proto) {
+ return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL,
+ -1, NULL, NULL, NULL);
+ }
+
+ bool HasSpanWithComment(char start_marker, char end_marker,
+ const Message& descriptor_proto,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
+ return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL,
+ -1, expected_leading_comments,
+ expected_trailing_comments,
+ expected_leading_detached_comments);
+ }
+
+ bool HasSpan(char start_marker, char end_marker,
+ const Message& descriptor_proto, const std::string& field_name) {
+ return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
+ }
+
+ bool HasSpan(char start_marker, char end_marker,
+ const Message& descriptor_proto, const std::string& field_name,
+ int index) {
+ return HasSpan(start_marker, end_marker, descriptor_proto, field_name,
+ index, NULL, NULL, NULL);
+ }
+
+ bool HasSpan(char start_marker, char end_marker,
+ const Message& descriptor_proto, const std::string& field_name,
+ int index, const char* expected_leading_comments,
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
+ const FieldDescriptor* field =
+ descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
+ if (field == NULL) {
+ ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
+ << " has no such field: " << field_name;
+ return false;
+ }
+
+ return HasSpanWithComment(start_marker, end_marker, descriptor_proto, field,
+ index, expected_leading_comments,
+ expected_trailing_comments,
+ expected_leading_detached_comments);
+ }
+
+ bool HasSpan(const Message& descriptor_proto) {
+ return HasSpanWithComment('\0', '\0', descriptor_proto, NULL, -1, NULL,
+ NULL, NULL);
+ }
+
+ bool HasSpan(const Message& descriptor_proto, const std::string& field_name) {
+ return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
+ }
+
+ bool HasSpanWithComment(char start_marker, char end_marker,
+ const Message& descriptor_proto,
+ const FieldDescriptor* field, int index,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
+ std::pair<SpanMap::iterator, SpanMap::iterator> range =
+ spans_.equal_range(SpanKey(descriptor_proto, field, index));
+
+ if (start_marker == '\0') {
+ if (range.first == range.second) {
+ return false;
+ } else {
+ spans_.erase(range.first);
+ return true;
+ }
+ } else {
+ std::pair<int, int> start_pos = FindOrDie(markers_, start_marker);
+ std::pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+
+ RepeatedField<int> expected_span;
+ expected_span.Add(start_pos.first);
+ expected_span.Add(start_pos.second);
+ if (end_pos.first != start_pos.first) {
+ expected_span.Add(end_pos.first);
+ }
+ expected_span.Add(end_pos.second);
+
+ for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
+ if (CompareSpans(expected_span, iter->second->span())) {
+ if (expected_leading_comments == NULL) {
+ EXPECT_FALSE(iter->second->has_leading_comments());
+ } else {
+ EXPECT_TRUE(iter->second->has_leading_comments());
+ EXPECT_EQ(expected_leading_comments,
+ iter->second->leading_comments());
+ }
+ if (expected_trailing_comments == NULL) {
+ EXPECT_FALSE(iter->second->has_trailing_comments());
+ } else {
+ EXPECT_TRUE(iter->second->has_trailing_comments());
+ EXPECT_EQ(expected_trailing_comments,
+ iter->second->trailing_comments());
+ }
+ if (expected_leading_detached_comments == NULL) {
+ EXPECT_EQ(0, iter->second->leading_detached_comments_size());
+ } else {
+ EXPECT_EQ(
+ expected_leading_detached_comments,
+ Join(iter->second->leading_detached_comments(), "\n"));
+ }
+
+ spans_.erase(iter);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private:
+ struct SpanKey {
+ const Message* descriptor_proto;
+ const FieldDescriptor* field;
+ int index;
+
+ inline SpanKey() {}
+ inline SpanKey(const Message& descriptor_proto_param,
+ const FieldDescriptor* field_param, int index_param)
+ : descriptor_proto(&descriptor_proto_param),
+ field(field_param),
+ index(index_param) {}
+
+ inline bool operator<(const SpanKey& other) const {
+ if (descriptor_proto < other.descriptor_proto) return true;
+ if (descriptor_proto > other.descriptor_proto) return false;
+ if (field < other.field) return true;
+ if (field > other.field) return false;
+ return index < other.index;
+ }
+ };
+
+ typedef std::multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
+ SpanMap spans_;
+ std::map<char, std::pair<int, int> > markers_;
+ std::string text_without_markers_;
+
+ void ExtractMarkers(const char* text) {
+ markers_.clear();
+ text_without_markers_.clear();
+ int line = 0;
+ int column = 0;
+ while (*text != '\0') {
+ if (*text == '$') {
+ ++text;
+ GOOGLE_CHECK_NE('\0', *text);
+ if (*text == '$') {
+ text_without_markers_ += '$';
+ ++column;
+ } else {
+ markers_[*text] = std::make_pair(line, column);
+ ++text;
+ GOOGLE_CHECK_EQ('$', *text);
+ }
+ } else if (*text == '\n') {
+ ++line;
+ column = 0;
+ text_without_markers_ += *text;
+ } else {
+ text_without_markers_ += *text;
+ ++column;
+ }
+ ++text;
+ }
+ }
+};
+
+TEST_F(SourceInfoTest, BasicFileDecls) {
+ EXPECT_TRUE(
+ Parse("$a$syntax = \"proto2\";$i$\n"
+ "$b$package foo.bar;$c$\n"
+ "$d$import \"baz.proto\";$e$\n"
+ "$f$import\"qux.proto\";$h$\n"
+ "$j$import $k$public$l$ \"bar.proto\";$m$\n"
+ "$n$import $o$weak$p$ \"bar.proto\";$q$\n"
+ "\n"
+ "// comment ignored\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'q', file_));
+ EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
+ EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
+ EXPECT_TRUE(HasSpan('f', 'h', file_, "dependency", 1));
+ EXPECT_TRUE(HasSpan('j', 'm', file_, "dependency", 2));
+ EXPECT_TRUE(HasSpan('k', 'l', file_, "public_dependency", 0));
+ EXPECT_TRUE(HasSpan('n', 'q', file_, "dependency", 3));
+ EXPECT_TRUE(HasSpan('o', 'p', file_, "weak_dependency", 0));
+ EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
+}
+
+TEST_F(SourceInfoTest, Messages) {
+ EXPECT_TRUE(
+ Parse("$a$message $b$Foo$c$ {}$d$\n"
+ "$e$message $f$Bar$g$ {}$h$\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Fields) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
+ " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
+ "}\n"));
+
+ const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
+ const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
+
+ EXPECT_TRUE(HasSpan('a', 'i', field1));
+ EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
+ EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
+ EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
+ EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
+
+ EXPECT_TRUE(HasSpan('j', 'r', field2));
+ EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
+ EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
+ EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
+ EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Proto3Fields) {
+ EXPECT_TRUE(
+ Parse("syntax = \"proto3\";\n"
+ "message Foo {\n"
+ " $a$int32$b$ $c$bar$d$ = $e$1$f$;$g$\n"
+ " $h$repeated$i$ $j$X.Y$k$ $l$baz$m$ = $n$2$o$;$p$\n"
+ "}\n"));
+
+ const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
+ const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
+
+ EXPECT_TRUE(HasSpan('a', 'g', field1));
+ EXPECT_TRUE(HasSpan('a', 'b', field1, "type"));
+ EXPECT_TRUE(HasSpan('c', 'd', field1, "name"));
+ EXPECT_TRUE(HasSpan('e', 'f', field1, "number"));
+
+ EXPECT_TRUE(HasSpan('h', 'p', field2));
+ EXPECT_TRUE(HasSpan('h', 'i', field2, "label"));
+ EXPECT_TRUE(HasSpan('j', 'k', field2, "type_name"));
+ EXPECT_TRUE(HasSpan('l', 'm', field2, "name"));
+ EXPECT_TRUE(HasSpan('n', 'o', field2, "number"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_, "syntax"));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Extensions) {
+ EXPECT_TRUE(
+ Parse("$a$extend $b$Foo$c$ {\n"
+ " $d$optional$e$ int32 bar = 1;$f$\n"
+ " $g$repeated$h$ X.Y baz = 2;$i$\n"
+ "}$j$\n"
+ "$k$extend $l$Bar$m$ {\n"
+ " $n$optional int32 qux = 1;$o$\n"
+ "}$p$\n"));
+
+ const FieldDescriptorProto& field1 = file_.extension(0);
+ const FieldDescriptorProto& field2 = file_.extension(1);
+ const FieldDescriptorProto& field3 = file_.extension(2);
+
+ EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
+ EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
+
+ EXPECT_TRUE(HasSpan('d', 'f', field1));
+ EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
+
+ EXPECT_TRUE(HasSpan('g', 'i', field2));
+ EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
+
+ EXPECT_TRUE(HasSpan('n', 'o', field3));
+ EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(field1, "type"));
+ EXPECT_TRUE(HasSpan(field1, "name"));
+ EXPECT_TRUE(HasSpan(field1, "number"));
+ EXPECT_TRUE(HasSpan(field2, "type_name"));
+ EXPECT_TRUE(HasSpan(field2, "name"));
+ EXPECT_TRUE(HasSpan(field2, "number"));
+ EXPECT_TRUE(HasSpan(field3, "label"));
+ EXPECT_TRUE(HasSpan(field3, "type"));
+ EXPECT_TRUE(HasSpan(field3, "name"));
+ EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, NestedExtensions) {
+ EXPECT_TRUE(
+ Parse("message Message {\n"
+ " $a$extend $b$Foo$c$ {\n"
+ " $d$optional$e$ int32 bar = 1;$f$\n"
+ " $g$repeated$h$ X.Y baz = 2;$i$\n"
+ " }$j$\n"
+ " $k$extend $l$Bar$m$ {\n"
+ " $n$optional int32 qux = 1;$o$\n"
+ " }$p$\n"
+ "}\n"));
+
+ const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
+ const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
+ const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
+
+ EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
+ EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
+
+ EXPECT_TRUE(HasSpan('d', 'f', field1));
+ EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
+
+ EXPECT_TRUE(HasSpan('g', 'i', field2));
+ EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
+
+ EXPECT_TRUE(HasSpan('n', 'o', field3));
+ EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan(field1, "type"));
+ EXPECT_TRUE(HasSpan(field1, "name"));
+ EXPECT_TRUE(HasSpan(field1, "number"));
+ EXPECT_TRUE(HasSpan(field2, "type_name"));
+ EXPECT_TRUE(HasSpan(field2, "name"));
+ EXPECT_TRUE(HasSpan(field2, "number"));
+ EXPECT_TRUE(HasSpan(field3, "label"));
+ EXPECT_TRUE(HasSpan(field3, "type"));
+ EXPECT_TRUE(HasSpan(field3, "name"));
+ EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, ExtensionRanges) {
+ EXPECT_TRUE(
+ Parse("message Message {\n"
+ " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+ " $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
+ "}\n"));
+
+ const DescriptorProto::ExtensionRange& range1 =
+ file_.message_type(0).extension_range(0);
+ const DescriptorProto::ExtensionRange& range2 =
+ file_.message_type(0).extension_range(1);
+ const DescriptorProto::ExtensionRange& range3 =
+ file_.message_type(0).extension_range(2);
+
+ EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
+ EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
+
+ EXPECT_TRUE(HasSpan('b', 'e', range1));
+ EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+ EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
+
+ EXPECT_TRUE(HasSpan('f', 'g', range2));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
+
+ EXPECT_TRUE(HasSpan('j', 'm', range3));
+ EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
+ EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, ReservedRanges) {
+ EXPECT_TRUE(
+ Parse("message Message {\n"
+ " $a$reserved $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+ "}\n"));
+
+ const DescriptorProto::ReservedRange& range1 =
+ file_.message_type(0).reserved_range(0);
+ const DescriptorProto::ReservedRange& range2 =
+ file_.message_type(0).reserved_range(1);
+
+ EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "reserved_range"));
+
+ EXPECT_TRUE(HasSpan('b', 'e', range1));
+ EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+ EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
+
+ EXPECT_TRUE(HasSpan('f', 'g', range2));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Oneofs) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " $a$oneof $c$foo$d$ {\n"
+ " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n"
+ " }$r$\n"
+ "}\n"));
+
+ const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0);
+ const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+ EXPECT_TRUE(HasSpan('a', 'r', oneof_decl));
+ EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name"));
+
+ EXPECT_TRUE(HasSpan('e', 'k', field));
+ EXPECT_TRUE(HasSpan('e', 'f', field, "type"));
+ EXPECT_TRUE(HasSpan('g', 'h', field, "name"));
+ EXPECT_TRUE(HasSpan('i', 'j', field, "number"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedMessages) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " $a$message $b$Bar$c$ {\n"
+ " $d$message $e$Baz$f$ {}$g$\n"
+ " }$h$\n"
+ " $i$message $j$Qux$k$ {}$l$\n"
+ "}\n"));
+
+ const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+ const DescriptorProto& baz = bar.nested_type(0);
+ const DescriptorProto& qux = file_.message_type(0).nested_type(1);
+
+ EXPECT_TRUE(HasSpan('a', 'h', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('d', 'g', baz));
+ EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+ EXPECT_TRUE(HasSpan('i', 'l', qux));
+ EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Groups) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " message Bar {}\n"
+ " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
+ " $i$message Qux {}$j$\n"
+ " }$k$\n"
+ "}\n"));
+
+ const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+ const DescriptorProto& baz = file_.message_type(0).nested_type(1);
+ const DescriptorProto& qux = baz.nested_type(0);
+ const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+ EXPECT_TRUE(HasSpan('a', 'k', field));
+ EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
+ EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
+ EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
+ EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
+ EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
+
+ EXPECT_TRUE(HasSpan('a', 'k', baz));
+ EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+ EXPECT_TRUE(HasSpan('i', 'j', qux));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan(bar));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(qux, "name"));
+}
+
+TEST_F(SourceInfoTest, Enums) {
+ EXPECT_TRUE(
+ Parse("$a$enum $b$Foo$c$ {}$d$\n"
+ "$e$enum $f$Bar$g$ {}$h$\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, EnumValues) {
+ EXPECT_TRUE(
+ Parse("enum Foo {\n"
+ " $a$BAR$b$ = $c$1$d$;$e$\n"
+ " $f$BAZ$g$ = $h$2$i$;$j$\n"
+ "}"));
+
+ const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
+ const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
+
+ EXPECT_TRUE(HasSpan('a', 'e', bar));
+ EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
+ EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
+ EXPECT_TRUE(HasSpan('f', 'j', baz));
+ EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+ EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, EnumReservedRange) {
+ EXPECT_TRUE(
+ Parse("enum TestEnum {\n"
+ " $a$reserved $b$1$c$ to $d$10$e$;$f$\n"
+ "}"));
+
+ const EnumDescriptorProto::EnumReservedRange& bar =
+ file_.enum_type(0).reserved_range(0);
+
+ EXPECT_TRUE(HasSpan('a', 'f', file_.enum_type(0), "reserved_range"));
+ EXPECT_TRUE(HasSpan('b', 'e', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "start"));
+ EXPECT_TRUE(HasSpan('d', 'e', bar, "end"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, EnumReservedName) {
+ EXPECT_TRUE(
+ Parse("enum TestEnum {\n"
+ " $a$reserved $b$'foo'$c$;$d$\n"
+ "}"));
+
+ const EnumDescriptorProto& bar = file_.enum_type(0);
+
+ EXPECT_TRUE(HasSpan('a', 'd', bar, "reserved_name"));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "reserved_name", 0));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedEnums) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " $a$enum $b$Bar$c$ {}$d$\n"
+ " $e$enum $f$Baz$g$ {}$h$\n"
+ "}\n"));
+
+ const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
+ const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
+
+ EXPECT_TRUE(HasSpan('a', 'd', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', baz));
+ EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Services) {
+ EXPECT_TRUE(
+ Parse("$a$service $b$Foo$c$ {}$d$\n"
+ "$e$service $f$Bar$g$ {}$h$\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, MethodsAndStreams) {
+ EXPECT_TRUE(
+ Parse("service Foo {\n"
+ " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
+ " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
+ "}"));
+
+ const MethodDescriptorProto& bar = file_.service(0).method(0);
+ const MethodDescriptorProto& baz = file_.service(0).method(1);
+
+ EXPECT_TRUE(HasSpan('a', 'h', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
+ EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
+
+ EXPECT_TRUE(HasSpan('i', 'p', baz));
+ EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
+ EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
+ EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.service(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+}
+
+
+TEST_F(SourceInfoTest, Options) {
+ EXPECT_TRUE(
+ Parse("$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
+ "$h$123$i$;$j$\n"
+ "$k$option qux = $l$-123$m$;$n$\n"
+ "$o$option corge = $p$abc$q$;$r$\n"
+ "$s$option grault = $t$'blah'$u$;$v$\n"
+ "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
+ "$0$option waldo = $1$123.0$2$;$3$\n"));
+
+ const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
+ const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
+ const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
+ const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
+ const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
+ const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
+
+ EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
+ EXPECT_TRUE(HasSpan('a', 'j', option1));
+ EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
+ EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
+ EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
+ EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
+
+ EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
+ EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
+
+ EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
+ EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
+
+ EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
+ EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
+
+ EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
+ EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
+
+ EXPECT_TRUE(HasSpan('0', '3', file_.options()));
+ EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(option2));
+ EXPECT_TRUE(HasSpan(option3));
+ EXPECT_TRUE(HasSpan(option4));
+ EXPECT_TRUE(HasSpan(option5));
+ EXPECT_TRUE(HasSpan(option6));
+ EXPECT_TRUE(HasSpan(option2, "name"));
+ EXPECT_TRUE(HasSpan(option3, "name"));
+ EXPECT_TRUE(HasSpan(option4, "name"));
+ EXPECT_TRUE(HasSpan(option5, "name"));
+ EXPECT_TRUE(HasSpan(option6, "name"));
+ EXPECT_TRUE(HasSpan(option2.name(0)));
+ EXPECT_TRUE(HasSpan(option3.name(0)));
+ EXPECT_TRUE(HasSpan(option4.name(0)));
+ EXPECT_TRUE(HasSpan(option5.name(0)));
+ EXPECT_TRUE(HasSpan(option6.name(0)));
+ EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
+}
+
+TEST_F(SourceInfoTest, ScopedOptions) {
+ EXPECT_TRUE(
+ Parse("message Foo {\n"
+ " $a$option mopt = 1;$b$\n"
+ "}\n"
+ "enum Bar {\n"
+ " $c$option eopt = 1;$d$\n"
+ "}\n"
+ "service Baz {\n"
+ " $e$option sopt = 1;$f$\n"
+ " rpc M(X) returns(Y) {\n"
+ " $g$option mopt = 1;$h$\n"
+ " }\n"
+ " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
+ " $k$option mopt = 1;$l$\n"
+ " }\n"
+ "}\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
+ EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
+ EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
+ EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0)));
+ EXPECT_TRUE(
+ HasSpan(file_.message_type(0).options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(
+ HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(
+ HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0),
+ "name_part"));
+ EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0),
+ "positive_int_value"));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0)));
+ EXPECT_TRUE(
+ HasSpan(file_.enum_type(0).options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(
+ HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(
+ HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0),
+ "name_part"));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0),
+ "positive_int_value"));
+ EXPECT_TRUE(HasSpan(file_.service(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0)));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).options().uninterpreted_option(0).name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0),
+ "positive_int_value"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).method(0).options().uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(0).options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(0).options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(0).options().uninterpreted_option(0).name(0),
+ "name_part"));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).method(0).options().uninterpreted_option(0),
+ "positive_int_value"));
+
+ EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).method(1).options().uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(1).options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(1).options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(
+ file_.service(0).method(1).options().uninterpreted_option(0).name(0),
+ "name_part"));
+ EXPECT_TRUE(
+ HasSpan(file_.service(0).method(1).options().uninterpreted_option(0),
+ "positive_int_value"));
+ EXPECT_TRUE(
+ HasSpan('1', '2', file_.service(0).method(1), "client_streaming"));
+ EXPECT_TRUE(
+ HasSpan('3', '4', file_.service(0).method(1), "server_streaming"));
+}
+
+TEST_F(SourceInfoTest, FieldOptions) {
+ // The actual "name = value" pairs are parsed by the same code as for
+ // top-level options so we won't re-test that -- just make sure that the
+ // syntax used for field options is understood.
+ EXPECT_TRUE(
+ Parse("message Foo {"
+ " optional int32 bar = 1 "
+ "$a$[default=$b$123$c$,$d$opt1=123$e$,"
+ "$f$opt2='hi'$g$]$h$;"
+ "}\n"));
+
+ const FieldDescriptorProto& field = file_.message_type(0).field(0);
+ const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
+ const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
+
+ EXPECT_TRUE(HasSpan('a', 'h', field.options()));
+ EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
+ EXPECT_TRUE(HasSpan('d', 'e', option1));
+ EXPECT_TRUE(HasSpan('f', 'g', option2));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.message_type(0)));
+ EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan(field));
+ EXPECT_TRUE(HasSpan(field, "label"));
+ EXPECT_TRUE(HasSpan(field, "type"));
+ EXPECT_TRUE(HasSpan(field, "name"));
+ EXPECT_TRUE(HasSpan(field, "number"));
+ EXPECT_TRUE(HasSpan(option1, "name"));
+ EXPECT_TRUE(HasSpan(option2, "name"));
+ EXPECT_TRUE(HasSpan(option1.name(0)));
+ EXPECT_TRUE(HasSpan(option2.name(0)));
+ EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+ EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, EnumValueOptions) {
+ // The actual "name = value" pairs are parsed by the same code as for
+ // top-level options so we won't re-test that -- just make sure that the
+ // syntax used for enum options is understood.
+ EXPECT_TRUE(
+ Parse("enum Foo {"
+ " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
+ "}\n"));
+
+ const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
+ const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
+ const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
+
+ EXPECT_TRUE(HasSpan('a', 'f', value.options()));
+ EXPECT_TRUE(HasSpan('b', 'c', option1));
+ EXPECT_TRUE(HasSpan('d', 'e', option2));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+ EXPECT_TRUE(HasSpan(value));
+ EXPECT_TRUE(HasSpan(value, "name"));
+ EXPECT_TRUE(HasSpan(value, "number"));
+ EXPECT_TRUE(HasSpan(option1, "name"));
+ EXPECT_TRUE(HasSpan(option2, "name"));
+ EXPECT_TRUE(HasSpan(option1.name(0)));
+ EXPECT_TRUE(HasSpan(option2.name(0)));
+ EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+ EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments) {
+ EXPECT_TRUE(
+ Parse("// Foo leading\n"
+ "// line 2\n"
+ "$a$message Foo {\n"
+ " // Foo trailing\n"
+ " // line 2\n"
+ "\n"
+ " // detached\n"
+ "\n"
+ " // bar leading\n"
+ " $b$optional int32 bar = 1;$c$\n"
+ " // bar trailing\n"
+ "}$d$\n"
+ "// ignored\n"));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+
+ EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
+ " Foo trailing\n line 2\n", NULL));
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
+ " bar trailing\n", " detached\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+}
+
+TEST_F(SourceInfoTest, DocComments2) {
+ EXPECT_TRUE(
+ Parse("// detached before message.\n"
+ "\n"
+ "// Foo leading\n"
+ "// line 2\n"
+ "$a$message Foo {\n"
+ " /* Foo trailing\n"
+ " * line 2 */\n"
+ " // detached\n"
+ " /* bar leading\n"
+ " */"
+ " $b$optional int32 bar = 1;$c$ // bar trailing\n"
+ " // ignored detached\n"
+ "}$d$\n"
+ "// ignored\n"
+ "\n"
+ "// detached before option\n"
+ "\n"
+ "// option leading\n"
+ "$e$option baz = 123;$f$\n"
+ "// option trailing\n"));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+ const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
+
+ EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
+ " Foo trailing\n line 2 ",
+ " detached before message.\n"));
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
+ " bar trailing\n", " detached\n"));
+ EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n",
+ " option trailing\n",
+ " detached before option\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+ EXPECT_TRUE(HasSpan(file_.options()));
+ EXPECT_TRUE(HasSpan(baz, "name"));
+ EXPECT_TRUE(HasSpan(baz.name(0)));
+ EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments3) {
+ EXPECT_TRUE(
+ Parse("$a$message Foo {\n"
+ " // bar leading\n"
+ " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
+ " // bar trailing\n"
+ "}$d$\n"
+ "// ignored\n"));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
+ " bar trailing\n", NULL));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+ EXPECT_TRUE(HasSpan(bar.options()));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(
+ HasSpan(bar.options().uninterpreted_option(0).name(0), "name_part"));
+ EXPECT_TRUE(
+ HasSpan(bar.options().uninterpreted_option(0), "aggregate_value"));
+}
+
+TEST_F(SourceInfoTest, DocCommentsTopLevel) {
+ EXPECT_TRUE(
+ Parse("// detached before syntax paragraph 1\n"
+ "\n"
+ "// detached before syntax paragraph 2\n"
+ "\n"
+ "// syntax leading\n"
+ "$a$syntax = \"proto2\";$b$\n"
+ "// syntax trailing\n"
+ "\n"
+ "// syntax-package detached comments\n"
+ "\n"
+ ";\n"
+ "\n"
+ "// detached after empty before package\n"
+ "\n"
+ "// package leading\n"
+ "$c$package foo;$d$\n"
+ "// package trailing\n"
+ "\n"
+ "// ignored detach\n"
+ "\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, " syntax leading\n",
+ " syntax trailing\n",
+ " detached before syntax paragraph 1\n"
+ "\n"
+ " detached before syntax paragraph 2\n"));
+ EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, " package leading\n",
+ " package trailing\n",
+ " syntax-package detached comments\n"
+ "\n"
+ " detached after empty before package\n"));
+
+ // ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, DocCommentsOneof) {
+ EXPECT_TRUE(
+ Parse("// Foo leading\n"
+ "$a$message Foo {\n"
+ " /* Foo trailing\n"
+ " */\n"
+ " // detached before oneof\n"
+ " /* bar leading\n"
+ " * line 2 */\n"
+ " $b$oneof bar {\n"
+ " /* bar trailing\n"
+ " * line 2 */\n"
+ " // detached before bar_int\n"
+ " /* bar_int leading\n"
+ " */\n"
+ " $c$int32 bar_int = 1;$d$ // bar_int trailing\n"
+ " // detach comment ignored\n"
+ " }$e$\n"
+ "}$f$\n"));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const OneofDescriptorProto& bar = foo.oneof_decl(0);
+ const FieldDescriptorProto& bar_int = foo.field(0);
+
+ EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n",
+ " Foo trailing\n", NULL));
+ EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ",
+ " bar trailing\n line 2 ",
+ " detached before oneof\n"));
+ EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n",
+ " bar_int trailing\n",
+ " detached before bar_int\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar_int, "type"));
+ EXPECT_TRUE(HasSpan(bar_int, "name"));
+ EXPECT_TRUE(HasSpan(bar_int, "number"));
+}
+
+// ===================================================================
+
+} // anonymous namespace
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.cc
new file mode 100644
index 00000000..31914f38
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.cc
@@ -0,0 +1,2325 @@
+// 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 <compiler/php/php_generator.h>
+
+#include <compiler/code_generator.h>
+#include <compiler/plugin.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+
+#include <sstream>
+
+const std::string kDescriptorFile = "google/protobuf/descriptor.proto";
+const std::string kEmptyFile = "google/protobuf/empty.proto";
+const std::string kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php";
+const std::string kDescriptorMetadataFile =
+ "GPBMetadata/Google/Protobuf/Internal/Descriptor.php";
+const std::string kDescriptorDirName = "Google/Protobuf/Internal";
+const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
+const char* const kReservedNames[] = {
+ "abstract", "and", "array", "as", "break",
+ "callable", "case", "catch", "class", "clone",
+ "const", "continue", "declare", "default", "die",
+ "do", "echo", "else", "elseif", "empty",
+ "enddeclare", "endfor", "endforeach", "endif", "endswitch",
+ "endwhile", "eval", "exit", "extends", "final",
+ "finally", "fn", "for", "foreach", "function",
+ "global", "goto", "if", "implements", "include",
+ "include_once", "instanceof", "insteadof", "interface", "isset",
+ "list", "match", "namespace", "new", "or",
+ "print", "private", "protected", "public", "require",
+ "require_once", "return", "static", "switch", "throw",
+ "trait", "try", "unset", "use", "var",
+ "while", "xor", "yield", "int", "float",
+ "bool", "string", "true", "false", "null",
+ "void", "iterable"};
+const char* const kValidConstantNames[] = {
+ "int", "float", "bool", "string", "true",
+ "false", "null", "void", "iterable",
+};
+const int kReservedNamesSize = 77;
+const int kValidConstantNamesSize = 9;
+const int kFieldSetter = 1;
+const int kFieldGetter = 2;
+const int kFieldProperty = 3;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+struct Options {
+ bool is_descriptor = false;
+ bool aggregate_metadata = false;
+ bool gen_c_wkt = false;
+ std::set<string> aggregate_metadata_prefixes;
+};
+
+namespace {
+
+// Forward decls.
+std::string PhpName(const std::string& full_name, const Options& options);
+std::string IntToString(int32 value);
+std::string FilenameToClassname(const std::string& filename);
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+ const Options& options);
+std::string UnderscoresToCamelCase(const std::string& name,
+ bool cap_first_letter);
+void Indent(io::Printer* printer);
+void Outdent(io::Printer* printer);
+void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
+ io::Printer* printer);
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+ const Options& options);
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+ const Descriptor* message,
+ const Options& options);
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+ const Options& options, int function_type);
+void GenerateWrapperFieldGetterDocComment(io::Printer* printer,
+ const FieldDescriptor* field);
+void GenerateWrapperFieldSetterDocComment(io::Printer* printer,
+ const FieldDescriptor* field);
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+ const Options& options);
+void GenerateEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value);
+void GenerateServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service);
+void GenerateServiceMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method);
+
+std::string ReservedNamePrefix(const std::string& classname,
+ const FileDescriptor* file) {
+ bool is_reserved = false;
+
+ std::string lower = classname;
+ std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+ for (int i = 0; i < kReservedNamesSize; i++) {
+ if (lower == kReservedNames[i]) {
+ is_reserved = true;
+ break;
+ }
+ }
+
+ if (is_reserved) {
+ if (file->package() == "google.protobuf") {
+ return "GPB";
+ } else {
+ return "PB";
+ }
+ }
+
+ return "";
+}
+
+template <typename DescriptorType>
+std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) {
+ if (is_internal) {
+ return StringReplace(desc->full_name(),
+ "google.protobuf",
+ "google.protobuf.internal", false);
+ } else {
+ return desc->full_name();
+ }
+}
+
+template <typename DescriptorType>
+std::string ClassNamePrefix(const std::string& classname,
+ const DescriptorType* desc) {
+ const std::string& prefix = (desc->file()->options()).php_class_prefix();
+ if (!prefix.empty()) {
+ return prefix;
+ }
+
+ return ReservedNamePrefix(classname, desc->file());
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassNameImpl(const DescriptorType* desc) {
+ std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
+ const Descriptor* containing = desc->containing_type();
+ while (containing != NULL) {
+ classname = ClassNamePrefix(containing->name(), desc) + containing->name()
+ + '\\' + classname;
+ containing = containing->containing_type();
+ }
+ return classname;
+}
+
+std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) {
+ std::string classname = desc->name();
+ return ClassNamePrefix(classname, desc) + classname;
+}
+
+template <typename DescriptorType>
+std::string LegacyGeneratedClassName(const DescriptorType* desc) {
+ std::string classname = desc->name();
+ const Descriptor* containing = desc->containing_type();
+ while (containing != NULL) {
+ classname = containing->name() + '_' + classname;
+ containing = containing->containing_type();
+ }
+ return ClassNamePrefix(classname, desc) + classname;
+}
+
+std::string ClassNamePrefix(const std::string& classname) {
+ std::string lower = classname;
+ std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+ for (int i = 0; i < kReservedNamesSize; i++) {
+ if (lower == kReservedNames[i]) {
+ return "PB";
+ }
+ }
+
+ return "";
+}
+
+std::string ConstantNamePrefix(const std::string& classname) {
+ bool is_reserved = false;
+
+ std::string lower = classname;
+ std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+ for (int i = 0; i < kReservedNamesSize; i++) {
+ if (lower == kReservedNames[i]) {
+ is_reserved = true;
+ break;
+ }
+ }
+
+ for (int i = 0; i < kValidConstantNamesSize; i++) {
+ if (lower == kValidConstantNames[i]) {
+ is_reserved = false;
+ break;
+ }
+ }
+
+ if (is_reserved) {
+ return "PB";
+ }
+
+ return "";
+}
+
+template <typename DescriptorType>
+std::string RootPhpNamespace(const DescriptorType* desc,
+ const Options& options) {
+ if (desc->file()->options().has_php_namespace()) {
+ const std::string& php_namespace = desc->file()->options().php_namespace();
+ if (!php_namespace.empty()) {
+ return php_namespace;
+ }
+ return "";
+ }
+
+ if (!desc->file()->package().empty()) {
+ return PhpName(desc->file()->package(), options);
+ }
+ return "";
+}
+
+template <typename DescriptorType>
+std::string FullClassName(const DescriptorType* desc, const Options& options) {
+ std::string classname = GeneratedClassNameImpl(desc);
+ std::string php_namespace = RootPhpNamespace(desc, options);
+ if (!php_namespace.empty()) {
+ return php_namespace + "\\" + classname;
+ }
+ return classname;
+}
+
+template <typename DescriptorType>
+std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
+ Options options;
+ options.is_descriptor = is_descriptor;
+ return FullClassName(desc, options);
+}
+
+template <typename DescriptorType>
+std::string LegacyFullClassName(const DescriptorType* desc,
+ const Options& options) {
+ std::string classname = LegacyGeneratedClassName(desc);
+ std::string php_namespace = RootPhpNamespace(desc, options);
+ if (!php_namespace.empty()) {
+ return php_namespace + "\\" + classname;
+ }
+ return classname;
+}
+
+std::string PhpName(const std::string& full_name, const Options& options) {
+ if (options.is_descriptor) {
+ return kDescriptorPackageName;
+ }
+
+ std::string segment;
+ std::string result;
+ bool cap_next_letter = true;
+ for (int i = 0; i < full_name.size(); i++) {
+ if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
+ segment += full_name[i] + ('A' - 'a');
+ cap_next_letter = false;
+ } else if (full_name[i] == '.') {
+ result += ClassNamePrefix(segment) + segment + '\\';
+ segment = "";
+ cap_next_letter = true;
+ } else {
+ segment += full_name[i];
+ cap_next_letter = false;
+ }
+ }
+ result += ClassNamePrefix(segment) + segment;
+ return result;
+}
+
+std::string DefaultForField(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_ENUM: return "0";
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT: return "0.0";
+ case FieldDescriptor::TYPE_BOOL: return "false";
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES: return "''";
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP: return "null";
+ default: assert(false); return "";
+ }
+}
+
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+ const Options& options) {
+ const std::string& proto_file = file->name();
+ int start_index = 0;
+ int first_index = proto_file.find_first_of("/", start_index);
+ std::string result = "";
+ std::string segment = "";
+
+ if (proto_file == kEmptyFile) {
+ return kEmptyMetadataFile;
+ }
+ if (options.is_descriptor) {
+ return kDescriptorMetadataFile;
+ }
+
+ // Append directory name.
+ std::string file_no_suffix;
+ int lastindex = proto_file.find_last_of(".");
+ if (proto_file == kEmptyFile) {
+ return kEmptyMetadataFile;
+ } else {
+ file_no_suffix = proto_file.substr(0, lastindex);
+ }
+
+ if (file->options().has_php_metadata_namespace()) {
+ const std::string& php_metadata_namespace =
+ file->options().php_metadata_namespace();
+ if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") {
+ result += php_metadata_namespace;
+ std::replace(result.begin(), result.end(), '\\', '/');
+ if (result.at(result.size() - 1) != '/') {
+ result += "/";
+ }
+ }
+ } else {
+ result += "GPBMetadata/";
+ while (first_index != std::string::npos) {
+ segment = UnderscoresToCamelCase(
+ file_no_suffix.substr(start_index, first_index - start_index), true);
+ result += ReservedNamePrefix(segment, file) + segment + "/";
+ start_index = first_index + 1;
+ first_index = file_no_suffix.find_first_of("/", start_index);
+ }
+ }
+
+ // Append file name.
+ int file_name_start = file_no_suffix.find_last_of("/");
+ if (file_name_start == std::string::npos) {
+ file_name_start = 0;
+ } else {
+ file_name_start += 1;
+ }
+ segment = UnderscoresToCamelCase(
+ file_no_suffix.substr(file_name_start, first_index - file_name_start), true);
+
+ return result + ReservedNamePrefix(segment, file) + segment + ".php";
+}
+
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+ bool is_descriptor) {
+ Options options;
+ options.is_descriptor = is_descriptor;
+ return GeneratedMetadataFileName(file, options);
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassFileName(const DescriptorType* desc,
+ const Options& options) {
+ std::string result = FullClassName(desc, options);
+ for (int i = 0; i < result.size(); i++) {
+ if (result[i] == '\\') {
+ result[i] = '/';
+ }
+ }
+ return result + ".php";
+}
+
+template <typename DescriptorType>
+std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
+ const Options& options) {
+ std::string result = LegacyFullClassName(desc, options);
+
+ for (int i = 0; i < result.size(); i++) {
+ if (result[i] == '\\') {
+ result[i] = '/';
+ }
+ }
+ return result + ".php";
+}
+
+std::string GeneratedServiceFileName(const ServiceDescriptor* service,
+ const Options& options) {
+ std::string result = FullClassName(service, options) + "Interface";
+ for (int i = 0; i < result.size(); i++) {
+ if (result[i] == '\\') {
+ result[i] = '/';
+ }
+ }
+ return result + ".php";
+}
+
+std::string IntToString(int32 value) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+}
+
+std::string LabelForField(const FieldDescriptor* field) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_OPTIONAL: return "optional";
+ case FieldDescriptor::LABEL_REQUIRED: return "required";
+ case FieldDescriptor::LABEL_REPEATED: return "repeated";
+ default: assert(false); return "";
+ }
+}
+
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+ const Options& options) {
+ if (field->is_map()) {
+ return "array|\\Google\\Protobuf\\Internal\\MapField";
+ }
+ std::string type;
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_ENUM:
+ type = "int";
+ break;
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ type = "int|string";
+ break;
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ type = "float";
+ break;
+ case FieldDescriptor::TYPE_BOOL:
+ type = "bool";
+ break;
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ type = "string";
+ break;
+ case FieldDescriptor::TYPE_MESSAGE:
+ type = "\\" + FullClassName(field->message_type(), options);
+ break;
+ case FieldDescriptor::TYPE_GROUP:
+ return "null";
+ default: assert(false); return "";
+ }
+ if (field->is_repeated()) {
+ // accommodate for edge case with multiple types.
+ size_t start_pos = type.find("|");
+ if (start_pos != std::string::npos) {
+ type.replace(start_pos, 1, "[]|");
+ }
+ type += "[]|\\Google\\Protobuf\\Internal\\RepeatedField";
+ }
+ return type;
+}
+
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+ bool is_descriptor) {
+ Options options;
+ options.is_descriptor = is_descriptor;
+ return PhpSetterTypeName(field, options);
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+ const Options& options) {
+ if (field->is_map()) {
+ return "\\Google\\Protobuf\\Internal\\MapField";
+ }
+ if (field->is_repeated()) {
+ return "\\Google\\Protobuf\\Internal\\RepeatedField";
+ }
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_ENUM: return "int";
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED64: return "int|string";
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT: return "float";
+ case FieldDescriptor::TYPE_BOOL: return "bool";
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES: return "string";
+ case FieldDescriptor::TYPE_MESSAGE:
+ return "\\" + FullClassName(field->message_type(), options);
+ case FieldDescriptor::TYPE_GROUP: return "null";
+ default: assert(false); return "";
+ }
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+ bool is_descriptor) {
+ Options options;
+ options.is_descriptor = is_descriptor;
+ return PhpGetterTypeName(field, options);
+}
+
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+ const Options& options) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ return ", '" +
+ DescriptorFullName(field->message_type(), options.is_descriptor) +
+ "'";
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ return ", '" +
+ DescriptorFullName(field->enum_type(), options.is_descriptor) + "'";
+ }
+ return "";
+}
+
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+ bool is_descriptor) {
+ Options options;
+ options.is_descriptor = is_descriptor;
+ return EnumOrMessageSuffix(field, options);
+}
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+std::string UnderscoresToCamelCase(const std::string& name,
+ bool cap_first_letter) {
+ std::string result;
+ for (int i = 0; i < name.size(); i++) {
+ if ('a' <= name[i] && name[i] <= 'z') {
+ if (cap_first_letter) {
+ result += name[i] + ('A' - 'a');
+ } else {
+ result += name[i];
+ }
+ cap_first_letter = false;
+ } else if ('A' <= name[i] && name[i] <= 'Z') {
+ if (i == 0 && !cap_first_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += name[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += name[i];
+ }
+ cap_first_letter = false;
+ } else if ('0' <= name[i] && name[i] <= '9') {
+ result += name[i];
+ cap_first_letter = true;
+ } else {
+ cap_first_letter = true;
+ }
+ }
+ // Add a trailing "_" if the name should be altered.
+ if (name[name.size() - 1] == '#') {
+ result += '_';
+ }
+ return result;
+}
+
+void Indent(io::Printer* printer) {
+ printer->Indent();
+ printer->Indent();
+}
+void Outdent(io::Printer* printer) {
+ printer->Outdent();
+ printer->Outdent();
+}
+
+void GenerateField(const FieldDescriptor* field, io::Printer* printer,
+ const Options& options) {
+ if (field->is_repeated()) {
+ GenerateFieldDocComment(printer, field, options, kFieldProperty);
+ printer->Print(
+ "private $^name^;\n",
+ "name", field->name());
+ } else if (field->real_containing_oneof()) {
+ // Oneof fields are handled by GenerateOneofField.
+ return;
+ } else {
+ std::string initial_value =
+ field->has_presence() ? "null" : DefaultForField(field);
+ GenerateFieldDocComment(printer, field, options, kFieldProperty);
+ printer->Print(
+ "protected $^name^ = ^initial_value^;\n",
+ "name", field->name(),
+ "initial_value", initial_value);
+ }
+}
+
+void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) {
+ // Oneof property needs to be protected in order to be accessed by parent
+ // class in implementation.
+ printer->Print(
+ "protected $^name^;\n",
+ "name", oneof->name());
+}
+
+void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
+ io::Printer* printer) {
+ const OneofDescriptor* oneof = field->real_containing_oneof();
+
+ // Generate getter.
+ GenerateFieldDocComment(printer, field, options, kFieldGetter);
+
+ // deprecation
+ std::string deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" +
+ field->name() + " is deprecated.', E_USER_DEPRECATED);\n " : "";
+
+ // Emit getter.
+ if (oneof != NULL) {
+ printer->Print(
+ "public function get^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^return $this->readOneof(^number^);\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "number", IntToString(field->number()),
+ "deprecation_trigger", deprecation_trigger);
+ } else if (field->has_presence() && !field->message_type()) {
+ printer->Print(
+ "public function get^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^return isset($this->^name^) ? $this->^name^ : ^default_value^;\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "name", field->name(),
+ "default_value", DefaultForField(field),
+ "deprecation_trigger", deprecation_trigger);
+ } else {
+ printer->Print(
+ "public function get^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^return $this->^name^;\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "name", field->name(),
+ "deprecation_trigger", deprecation_trigger);
+ }
+
+ // Emit hazzers/clear.
+ if (oneof) {
+ printer->Print(
+ "public function has^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^return $this->hasOneof(^number^);\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "number", IntToString(field->number()),
+ "deprecation_trigger", deprecation_trigger);
+ } else if (field->has_presence()) {
+ printer->Print(
+ "public function has^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^return isset($this->^name^);\n"
+ "}\n\n"
+ "public function clear^camel_name^()\n"
+ "{\n"
+ " ^deprecation_trigger^unset($this->^name^);\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "name", field->name(),
+ "default_value", DefaultForField(field),
+ "deprecation_trigger", deprecation_trigger);
+ }
+
+ // For wrapper types, generate an additional getXXXUnwrapped getter
+ if (!field->is_map() &&
+ !field->is_repeated() &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ IsWrapperType(field)) {
+ GenerateWrapperFieldGetterDocComment(printer, field);
+ printer->Print(
+ "public function get^camel_name^Unwrapped()\n"
+ "{\n"
+ " ^deprecation_trigger^return $this->readWrapperValue(\"^field_name^\");\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "field_name", field->name(),
+ "deprecation_trigger", deprecation_trigger);
+ }
+
+ // Generate setter.
+ GenerateFieldDocComment(printer, field, options, kFieldSetter);
+ printer->Print(
+ "public function set^camel_name^($var)\n"
+ "{\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true));
+
+ Indent(printer);
+
+ if (field->options().deprecated()) {
+ printer->Print(
+ "^deprecation_trigger^",
+ "deprecation_trigger", deprecation_trigger
+ );
+ }
+
+ // Type check.
+ if (field->is_map()) {
+ const Descriptor* map_entry = field->message_type();
+ const FieldDescriptor* key = map_entry->FindFieldByName("key");
+ const FieldDescriptor* value = map_entry->FindFieldByName("value");
+ printer->Print(
+ "$arr = GPBUtil::checkMapField($var, "
+ "\\Google\\Protobuf\\Internal\\GPBType::^key_type^, "
+ "\\Google\\Protobuf\\Internal\\GPBType::^value_type^",
+ "key_type", ToUpper(key->type_name()),
+ "value_type", ToUpper(value->type_name()));
+ if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \\^class_name^);\n",
+ "class_name",
+ FullClassName(value->message_type(), options) + "::class");
+ } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \\^class_name^);\n",
+ "class_name",
+ FullClassName(value->enum_type(), options) + "::class");
+ } else {
+ printer->Print(");\n");
+ }
+ } else if (field->is_repeated()) {
+ printer->Print(
+ "$arr = GPBUtil::checkRepeatedField($var, "
+ "\\Google\\Protobuf\\Internal\\GPBType::^type^",
+ "type", ToUpper(field->type_name()));
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \\^class_name^);\n",
+ "class_name",
+ FullClassName(field->message_type(), options) + "::class");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \\^class_name^);\n",
+ "class_name",
+ FullClassName(field->enum_type(), options) + "::class");
+ } else {
+ printer->Print(");\n");
+ }
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
+ "class_name", FullClassName(field->message_type(), options));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
+ "class_name", FullClassName(field->enum_type(), options));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ printer->Print(
+ "GPBUtil::checkString($var, ^utf8^);\n",
+ "utf8",
+ field->type() == FieldDescriptor::TYPE_STRING ? "True": "False");
+ } else {
+ printer->Print(
+ "GPBUtil::check^type^($var);\n",
+ "type", UnderscoresToCamelCase(field->cpp_type_name(), true));
+ }
+
+ if (oneof != NULL) {
+ printer->Print(
+ "$this->writeOneof(^number^, $var);\n",
+ "number", IntToString(field->number()));
+ } else if (field->is_repeated()) {
+ printer->Print(
+ "$this->^name^ = $arr;\n",
+ "name", field->name());
+ } else {
+ printer->Print(
+ "$this->^name^ = $var;\n",
+ "name", field->name());
+ }
+
+ printer->Print("\nreturn $this;\n");
+
+ Outdent(printer);
+
+ printer->Print(
+ "}\n\n");
+
+ // For wrapper types, generate an additional setXXXValue getter
+ if (!field->is_map() &&
+ !field->is_repeated() &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ IsWrapperType(field)) {
+ GenerateWrapperFieldSetterDocComment(printer, field);
+ printer->Print(
+ "public function set^camel_name^Unwrapped($var)\n"
+ "{\n"
+ " $this->writeWrapperValue(\"^field_name^\", $var);\n"
+ " return $this;"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "field_name", field->name());
+ }
+}
+
+void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
+ printer->Print(
+ "$pool->addEnum('^name^', "
+ "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
+ "name", DescriptorFullName(en, true),
+ "class_name", en->name());
+ Indent(printer);
+
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ printer->Print(
+ "->value(\"^name^\", ^number^)\n",
+ "name", ConstantNamePrefix(value->name()) + value->name(),
+ "number", IntToString(value->number()));
+ }
+ printer->Print("->finalizeToPool();\n\n");
+ Outdent(printer);
+}
+
+void GenerateServiceMethod(const MethodDescriptor* method,
+ io::Printer* printer) {
+ printer->Print(
+ "public function ^camel_name^(\\^request_name^ $request);\n\n",
+ "camel_name", UnderscoresToCamelCase(method->name(), false),
+ "request_name", FullClassName(
+ method->input_type(), false)
+ );
+}
+
+void GenerateMessageToPool(const std::string& name_prefix,
+ const Descriptor* message, io::Printer* printer) {
+ // Don't generate MapEntry messages -- we use the PHP extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+ std::string class_name =
+ (name_prefix.empty() ? "" : name_prefix + "\\") +
+ ReservedNamePrefix(message->name(), message->file()) + message->name();
+
+ printer->Print(
+ "$pool->addMessage('^message^', "
+ "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
+ "message", DescriptorFullName(message, true),
+ "class_name", class_name);
+
+ Indent(printer);
+
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ if (field->is_map()) {
+ const FieldDescriptor* key =
+ field->message_type()->FindFieldByName("key");
+ const FieldDescriptor* val =
+ field->message_type()->FindFieldByName("value");
+ printer->Print(
+ "->map('^field^', \\Google\\Protobuf\\Internal\\GPBType::^key^, "
+ "\\Google\\Protobuf\\Internal\\GPBType::^value^, ^number^^other^)\n",
+ "field", field->name(),
+ "key", ToUpper(key->type_name()),
+ "value", ToUpper(val->type_name()),
+ "number", StrCat(field->number()),
+ "other", EnumOrMessageSuffix(val, true));
+ } else if (!field->real_containing_oneof()) {
+ printer->Print(
+ "->^label^('^field^', "
+ "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
+ "field", field->name(),
+ "label", LabelForField(field),
+ "type", ToUpper(field->type_name()),
+ "number", StrCat(field->number()),
+ "other", EnumOrMessageSuffix(field, true));
+ }
+ }
+
+ // oneofs.
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ printer->Print("->oneof(^name^)\n",
+ "name", oneof->name());
+ Indent(printer);
+ for (int index = 0; index < oneof->field_count(); index++) {
+ const FieldDescriptor* field = oneof->field(index);
+ printer->Print(
+ "->value('^field^', "
+ "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
+ "field", field->name(),
+ "type", ToUpper(field->type_name()),
+ "number", StrCat(field->number()),
+ "other", EnumOrMessageSuffix(field, true));
+ }
+ printer->Print("->finish()\n");
+ Outdent(printer);
+ }
+
+ printer->Print(
+ "->finalizeToPool();\n");
+
+ Outdent(printer);
+
+ printer->Print(
+ "\n");
+
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateMessageToPool(class_name, message->nested_type(i), printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnumToPool(message->enum_type(i), printer);
+ }
+}
+
+void GenerateAddFileToPool(const FileDescriptor* file, const Options& options,
+ io::Printer* printer) {
+ printer->Print(
+ "public static $is_initialized = false;\n\n"
+ "public static function initOnce() {\n");
+ Indent(printer);
+
+ if (options.aggregate_metadata) {
+ GenerateAddFilesToPool(file, options, printer);
+ } else {
+ printer->Print(
+ "$pool = \\Google\\Protobuf\\Internal\\"
+ "DescriptorPool::getGeneratedPool();\n\n"
+ "if (static::$is_initialized == true) {\n"
+ " return;\n"
+ "}\n");
+
+ if (options.is_descriptor) {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateMessageToPool("", file->message_type(i), printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnumToPool(file->enum_type(i), printer);
+ }
+
+ printer->Print(
+ "$pool->finish();\n");
+ } else {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const std::string& name = file->dependency(i)->name();
+ // Currently, descriptor.proto is not ready for external usage. Skip to
+ // import it for now, so that its dependencies can still work as long as
+ // they don't use protos defined in descriptor.proto.
+ if (name == kDescriptorFile) {
+ continue;
+ }
+ std::string dependency_filename =
+ GeneratedMetadataFileName(file->dependency(i), options);
+ printer->Print(
+ "\\^name^::initOnce();\n",
+ "name", FilenameToClassname(dependency_filename));
+ }
+
+ // Add messages and enums to descriptor pool.
+ FileDescriptorSet files;
+ FileDescriptorProto* file_proto = files.add_file();
+ file->CopyTo(file_proto);
+
+ // Filter out descriptor.proto as it cannot be depended on for now.
+ RepeatedPtrField<std::string>* dependency =
+ file_proto->mutable_dependency();
+ for (RepeatedPtrField<std::string>::iterator it = dependency->begin();
+ it != dependency->end(); ++it) {
+ if (*it != kDescriptorFile) {
+ dependency->erase(it);
+ break;
+ }
+ }
+
+ // Filter out all extensions, since we do not support extension yet.
+ file_proto->clear_extension();
+ RepeatedPtrField<DescriptorProto>* message_type =
+ file_proto->mutable_message_type();
+ for (RepeatedPtrField<DescriptorProto>::iterator it = message_type->begin();
+ it != message_type->end(); ++it) {
+ it->clear_extension();
+ }
+
+ std::string files_data;
+ files.SerializeToString(&files_data);
+
+ printer->Print("$pool->internalAddGeneratedFile(\n");
+ Indent(printer);
+ printer->Print("'");
+
+ for (auto ch : files_data) {
+ switch (ch) {
+ case '\\':
+ printer->Print(R"(\\)");
+ break;
+ case '\'':
+ printer->Print(R"(\')");
+ break;
+ default:
+ printer->Print("^char^", "char", std::string(1, ch));
+ break;
+ }
+ }
+
+ printer->Print("'\n");
+ Outdent(printer);
+ printer->Print(
+ ", true);\n\n");
+ }
+ printer->Print(
+ "static::$is_initialized = true;\n");
+ }
+
+ Outdent(printer);
+ printer->Print("}\n");
+}
+
+static void AnalyzeDependencyForFile(
+ const FileDescriptor* file,
+ std::set<const FileDescriptor*>* nodes_without_dependency,
+ std::map<const FileDescriptor*, std::set<const FileDescriptor*>>* deps,
+ std::map<const FileDescriptor*, int>* dependency_count) {
+ int count = file->dependency_count();
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dependency = file->dependency(i);
+ if (dependency->name() == kDescriptorFile) {
+ count--;
+ break;
+ }
+ }
+
+ if (count == 0) {
+ nodes_without_dependency->insert(file);
+ } else {
+ (*dependency_count)[file] = count;
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const FileDescriptor* dependency = file->dependency(i);
+ if (dependency->name() == kDescriptorFile) {
+ continue;
+ }
+ if (deps->find(dependency) == deps->end()) {
+ (*deps)[dependency] = std::set<const FileDescriptor*>();
+ }
+ (*deps)[dependency].insert(file);
+ AnalyzeDependencyForFile(
+ dependency, nodes_without_dependency, deps, dependency_count);
+ }
+ }
+}
+
+static bool NeedsUnwrapping(const FileDescriptor* file,
+ const Options& options) {
+ bool has_aggregate_metadata_prefix = false;
+ if (options.aggregate_metadata_prefixes.empty()) {
+ has_aggregate_metadata_prefix = true;
+ } else {
+ for (const auto& prefix : options.aggregate_metadata_prefixes) {
+ if (HasPrefixString(file->package(), prefix)) {
+ has_aggregate_metadata_prefix = true;
+ break;
+ }
+ }
+ }
+
+ return has_aggregate_metadata_prefix;
+}
+
+void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
+ io::Printer* printer) {
+ printer->Print(
+ "$pool = \\Google\\Protobuf\\Internal\\"
+ "DescriptorPool::getGeneratedPool();\n"
+ "if (static::$is_initialized == true) {\n"
+ " return;\n"
+ "}\n");
+
+ // Sort files according to dependency
+ std::map<const FileDescriptor*, std::set<const FileDescriptor*>> deps;
+ std::map<const FileDescriptor*, int> dependency_count;
+ std::set<const FileDescriptor*> nodes_without_dependency;
+ FileDescriptorSet sorted_file_set;
+
+ AnalyzeDependencyForFile(
+ file, &nodes_without_dependency, &deps, &dependency_count);
+
+ while (!nodes_without_dependency.empty()) {
+ auto file_node = *nodes_without_dependency.begin();
+ nodes_without_dependency.erase(file_node);
+ for (auto dependent : deps[file_node]) {
+ if (dependency_count[dependent] == 1) {
+ dependency_count.erase(dependent);
+ nodes_without_dependency.insert(dependent);
+ } else {
+ dependency_count[dependent] -= 1;
+ }
+ }
+
+ bool needs_aggregate = NeedsUnwrapping(file_node, options);
+
+ if (needs_aggregate) {
+ auto file_proto = sorted_file_set.add_file();
+ file_node->CopyTo(file_proto);
+
+ // Filter out descriptor.proto as it cannot be depended on for now.
+ RepeatedPtrField<std::string>* dependency =
+ file_proto->mutable_dependency();
+ for (RepeatedPtrField<std::string>::iterator it = dependency->begin();
+ it != dependency->end(); ++it) {
+ if (*it != kDescriptorFile) {
+ dependency->erase(it);
+ break;
+ }
+ }
+
+ // Filter out all extensions, since we do not support extension yet.
+ file_proto->clear_extension();
+ RepeatedPtrField<DescriptorProto>* message_type =
+ file_proto->mutable_message_type();
+ for (RepeatedPtrField<DescriptorProto>::iterator it = message_type->begin();
+ it != message_type->end(); ++it) {
+ it->clear_extension();
+ }
+ } else {
+ std::string dependency_filename = GeneratedMetadataFileName(file_node, false);
+ printer->Print(
+ "\\^name^::initOnce();\n",
+ "name", FilenameToClassname(dependency_filename));
+ }
+ }
+
+ std::string files_data;
+ sorted_file_set.SerializeToString(&files_data);
+
+ printer->Print("$pool->internalAddGeneratedFile(\n");
+ Indent(printer);
+ printer->Print("'");
+
+ for (auto ch : files_data) {
+ switch (ch) {
+ case '\\':
+ printer->Print(R"(\\)");
+ break;
+ case '\'':
+ printer->Print(R"(\')");
+ break;
+ default:
+ printer->Print("^char^", "char", std::string(1, ch));
+ break;
+ }
+ }
+
+ printer->Print("'\n");
+ Outdent(printer);
+ printer->Print(
+ ", true);\n");
+
+ printer->Print(
+ "static::$is_initialized = true;\n");
+}
+
+void GenerateUseDeclaration(const Options& options, io::Printer* printer) {
+ if (!options.is_descriptor) {
+ printer->Print(
+ "use Google\\Protobuf\\Internal\\GPBType;\n"
+ "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+ "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+ } else {
+ printer->Print(
+ "use Google\\Protobuf\\Internal\\GPBType;\n"
+ "use Google\\Protobuf\\Internal\\GPBWire;\n"
+ "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+ "use Google\\Protobuf\\Internal\\InputStream;\n"
+ "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+ }
+}
+
+void GenerateHead(const FileDescriptor* file, io::Printer* printer) {
+ printer->Print(
+ "<?php\n"
+ "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "# source: ^filename^\n"
+ "\n",
+ "filename", file->name());
+}
+
+std::string FilenameToClassname(const std::string& filename) {
+ int lastindex = filename.find_last_of(".");
+ std::string result = filename.substr(0, lastindex);
+ for (int i = 0; i < result.size(); i++) {
+ if (result[i] == '/') {
+ result[i] = '\\';
+ }
+ }
+ return result;
+}
+
+void GenerateMetadataFile(const FileDescriptor* file, const Options& options,
+ GeneratorContext* generator_context) {
+ std::string filename = GeneratedMetadataFileName(file, options);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '^');
+
+ GenerateHead(file, &printer);
+
+ std::string fullname = FilenameToClassname(filename);
+ int lastindex = fullname.find_last_of("\\");
+
+ if (lastindex != std::string::npos) {
+ printer.Print(
+ "namespace ^name^;\n\n",
+ "name", fullname.substr(0, lastindex));
+
+ printer.Print(
+ "class ^name^\n"
+ "{\n",
+ "name", fullname.substr(lastindex + 1));
+ } else {
+ printer.Print(
+ "class ^name^\n"
+ "{\n",
+ "name", fullname);
+ }
+ Indent(&printer);
+
+ GenerateAddFileToPool(file, options, &printer);
+
+ Outdent(&printer);
+ printer.Print("}\n\n");
+}
+
+template <typename DescriptorType>
+void LegacyGenerateClassFile(const FileDescriptor* file,
+ const DescriptorType* desc, const Options& options,
+ GeneratorContext* generator_context) {
+ std::string filename = LegacyGeneratedClassFileName(desc, options);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '^');
+
+ GenerateHead(file, &printer);
+
+ std::string php_namespace = RootPhpNamespace(desc, options);
+ if (!php_namespace.empty()) {
+ printer.Print(
+ "namespace ^name^;\n\n",
+ "name", php_namespace);
+ }
+ std::string newname = FullClassName(desc, options);
+ printer.Print("if (false) {\n");
+ Indent(&printer);
+ printer.Print("/**\n");
+ printer.Print(" * This class is deprecated. Use ^new^ instead.\n",
+ "new", newname);
+ printer.Print(" * @deprecated\n");
+ printer.Print(" */\n");
+ printer.Print("class ^old^ {}\n",
+ "old", LegacyGeneratedClassName(desc));
+ Outdent(&printer);
+ printer.Print("}\n");
+ printer.Print("class_exists(^new^::class);\n",
+ "new", GeneratedClassNameImpl(desc));
+ printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
+ "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
+ "old", LegacyFullClassName(desc, options),
+ "fullname", newname);
+}
+
+void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
+ const Options& options,
+ GeneratorContext* generator_context) {
+ std::string filename = GeneratedClassFileName(en, options);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '^');
+
+ GenerateHead(file, &printer);
+
+ std::string fullname = FilenameToClassname(filename);
+ int lastindex = fullname.find_last_of("\\");
+
+ if (lastindex != std::string::npos) {
+ printer.Print(
+ "namespace ^name^;\n\n",
+ "name", fullname.substr(0, lastindex));
+
+ // We only need this 'use' statement if the enum has a namespace.
+ // Otherwise, we get a warning that the use statement has no effect.
+ printer.Print("use UnexpectedValueException;\n\n");
+ }
+
+ GenerateEnumDocComment(&printer, en, options);
+
+ if (lastindex != std::string::npos) {
+ fullname = fullname.substr(lastindex + 1);
+ }
+
+ printer.Print(
+ "class ^name^\n"
+ "{\n",
+ "name", fullname);
+ Indent(&printer);
+
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ GenerateEnumValueDocComment(&printer, value);
+ printer.Print("const ^name^ = ^number^;\n",
+ "name", ConstantNamePrefix(value->name()) + value->name(),
+ "number", IntToString(value->number()));
+ }
+
+ printer.Print("\nprivate static $valueToName = [\n");
+ Indent(&printer);
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ printer.Print("self::^name^ => '^name^',\n",
+ "name", ConstantNamePrefix(value->name()) + value->name());
+ }
+ Outdent(&printer);
+ printer.Print("];\n");
+
+ printer.Print(
+ "\npublic static function name($value)\n"
+ "{\n");
+ Indent(&printer);
+ printer.Print("if (!isset(self::$valueToName[$value])) {\n");
+ Indent(&printer);
+ printer.Print("throw new UnexpectedValueException(sprintf(\n");
+ Indent(&printer);
+ Indent(&printer);
+ printer.Print("'Enum %s has no name defined for value %s', __CLASS__, $value));\n");
+ Outdent(&printer);
+ Outdent(&printer);
+ Outdent(&printer);
+ printer.Print("}\n"
+ "return self::$valueToName[$value];\n");
+ Outdent(&printer);
+ printer.Print("}\n\n");
+
+ printer.Print(
+ "\npublic static function value($name)\n"
+ "{\n");
+ Indent(&printer);
+ printer.Print("$const = __CLASS__ . '::' . strtoupper($name);\n"
+ "if (!defined($const)) {\n");
+ Indent(&printer);
+ printer.Print("throw new UnexpectedValueException(sprintf(\n");
+ Indent(&printer);
+ Indent(&printer);
+ printer.Print("'Enum %s has no value defined for name %s', __CLASS__, $name));\n");
+ Outdent(&printer);
+ Outdent(&printer);
+ Outdent(&printer);
+ printer.Print("}\n"
+ "return constant($const);\n");
+ Outdent(&printer);
+ printer.Print("}\n");
+
+ Outdent(&printer);
+ printer.Print("}\n\n");
+
+ // write legacy file for backwards compatibility with nested messages and enums
+ if (en->containing_type() != NULL) {
+ printer.Print(
+ "// Adding a class alias for backwards compatibility with the previous class name.\n");
+ printer.Print(
+ "class_alias(^new^::class, \\^old^::class);\n\n",
+ "new", fullname,
+ "old", LegacyFullClassName(en, options));
+ LegacyGenerateClassFile(file, en, options, generator_context);
+ }
+}
+
+void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
+ const Options& options,
+ GeneratorContext* generator_context) {
+ // Don't generate MapEntry messages -- we use the PHP extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
+ std::string filename = GeneratedClassFileName(message, options);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '^');
+
+ GenerateHead(file, &printer);
+
+ std::string fullname = FilenameToClassname(filename);
+ int lastindex = fullname.find_last_of("\\");
+
+ if (lastindex != std::string::npos) {
+ printer.Print(
+ "namespace ^name^;\n\n",
+ "name", fullname.substr(0, lastindex));
+ }
+
+ GenerateUseDeclaration(options, &printer);
+
+ GenerateMessageDocComment(&printer, message, options);
+ if (lastindex != std::string::npos) {
+ fullname = fullname.substr(lastindex + 1);
+ }
+
+ std::string base;
+
+ switch (message->well_known_type()) {
+ case Descriptor::WELLKNOWNTYPE_ANY:
+ base = "\\Google\\Protobuf\\Internal\\AnyBase";
+ break;
+ case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+ base = "\\Google\\Protobuf\\Internal\\TimestampBase";
+ break;
+ default:
+ base = "\\Google\\Protobuf\\Internal\\Message";
+ break;
+ }
+
+ printer.Print(
+ "class ^name^ extends ^base^\n"
+ "{\n",
+ "base", base,
+ "name", fullname);
+ Indent(&printer);
+
+ // Field and oneof definitions.
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ GenerateField(field, &printer, options);
+ }
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ GenerateOneofField(oneof, &printer);
+ }
+ printer.Print("\n");
+
+ GenerateMessageConstructorDocComment(&printer, message, options);
+ printer.Print(
+ "public function __construct($data = NULL) {\n");
+ Indent(&printer);
+
+ std::string metadata_filename = GeneratedMetadataFileName(file, options);
+ std::string metadata_fullname = FilenameToClassname(metadata_filename);
+ printer.Print(
+ "\\^fullname^::initOnce();\n",
+ "fullname", metadata_fullname);
+
+ printer.Print(
+ "parent::__construct($data);\n");
+
+ Outdent(&printer);
+ printer.Print("}\n\n");
+
+ // Field and oneof accessors.
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ GenerateFieldAccessor(field, options, &printer);
+ }
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ printer.Print(
+ "/**\n"
+ " * @return string\n"
+ " */\n"
+ "public function get^camel_name^()\n"
+ "{\n"
+ " return $this->whichOneof(\"^name^\");\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(oneof->name(), true), "name",
+ oneof->name());
+ }
+
+ Outdent(&printer);
+ printer.Print("}\n\n");
+
+ // write legacy file for backwards compatibility with nested messages and enums
+ if (message->containing_type() != NULL) {
+ printer.Print(
+ "// Adding a class alias for backwards compatibility with the previous class name.\n");
+ printer.Print(
+ "class_alias(^new^::class, \\^old^::class);\n\n",
+ "new", fullname,
+ "old", LegacyFullClassName(message, options));
+ LegacyGenerateClassFile(file, message, options, generator_context);
+ }
+
+ // Nested messages and enums.
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateMessageFile(file, message->nested_type(i), options,
+ generator_context);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnumFile(file, message->enum_type(i), options, generator_context);
+ }
+}
+
+void GenerateServiceFile(
+ const FileDescriptor* file, const ServiceDescriptor* service,
+ const Options& options, GeneratorContext* generator_context) {
+ std::string filename = GeneratedServiceFileName(service, options);
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '^');
+
+ GenerateHead(file, &printer);
+
+ std::string fullname = FilenameToClassname(filename);
+ int lastindex = fullname.find_last_of("\\");
+
+ if (!file->options().php_namespace().empty() ||
+ (!file->options().has_php_namespace() && !file->package().empty()) ||
+ lastindex != std::string::npos) {
+ printer.Print(
+ "namespace ^name^;\n\n",
+ "name", fullname.substr(0, lastindex));
+ }
+
+ GenerateServiceDocComment(&printer, service);
+
+ if (lastindex != std::string::npos) {
+ printer.Print(
+ "interface ^name^\n"
+ "{\n",
+ "name", fullname.substr(lastindex + 1));
+ } else {
+ printer.Print(
+ "interface ^name^\n"
+ "{\n",
+ "name", fullname);
+ }
+
+ Indent(&printer);
+
+ for (int i = 0; i < service->method_count(); i++) {
+ const MethodDescriptor* method = service->method(i);
+ GenerateServiceMethodDocComment(&printer, method);
+ GenerateServiceMethod(method, &printer);
+ }
+
+ Outdent(&printer);
+ printer.Print("}\n\n");
+}
+
+void GenerateFile(const FileDescriptor* file, const Options& options,
+ GeneratorContext* generator_context) {
+ GenerateMetadataFile(file, options, generator_context);
+
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateMessageFile(file, file->message_type(i), options,
+ generator_context);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnumFile(file, file->enum_type(i), options, generator_context);
+ }
+ if (file->options().php_generic_services()) {
+ for (int i = 0; i < file->service_count(); i++) {
+ GenerateServiceFile(file, file->service(i), options, generator_context);
+ }
+ }
+}
+
+static std::string EscapePhpdoc(const std::string& input) {
+ std::string result;
+ result.reserve(input.size() * 2);
+
+ char prev = '*';
+
+ for (std::string::size_type i = 0; i < input.size(); i++) {
+ char c = input[i];
+ switch (c) {
+ case '*':
+ // Avoid "/*".
+ if (prev == '/') {
+ result.append("&#42;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '/':
+ // Avoid "*/".
+ if (prev == '*') {
+ result.append("&#47;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '@':
+ // '@' starts phpdoc tags including the @deprecated tag, which will
+ // cause a compile-time error if inserted before a declaration that
+ // does not have a corresponding @Deprecated annotation.
+ result.append("&#64;");
+ break;
+ default:
+ result.push_back(c);
+ break;
+ }
+
+ prev = c;
+ }
+
+ return result;
+}
+
+static void GenerateDocCommentBodyForLocation(
+ io::Printer* printer, const SourceLocation& location, bool trailingNewline,
+ int indentCount) {
+ std::string comments = location.leading_comments.empty()
+ ? location.trailing_comments
+ : location.leading_comments;
+ if (!comments.empty()) {
+ // TODO(teboring): Ideally we should parse the comment text as Markdown and
+ // write it back as HTML, but this requires a Markdown parser. For now
+ // we just use the proto comments unchanged.
+
+ // If the comment itself contains block comment start or end markers,
+ // HTML-escape them so that they don't accidentally close the doc comment.
+ comments = EscapePhpdoc(comments);
+
+ std::vector<std::string> lines = Split(comments, "\n", true);
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+
+ for (int i = 0; i < lines.size(); i++) {
+ // Most lines should start with a space. Watch out for lines that start
+ // with a /, since putting that right after the leading asterisk will
+ // close the comment.
+ if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') {
+ printer->Print(" * ^line^\n", "line", lines[i]);
+ } else {
+ std::string indent = std::string(indentCount, ' ');
+ printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]);
+ }
+ }
+ if (trailingNewline) {
+ printer->Print(" *\n");
+ }
+ }
+}
+
+template <typename DescriptorType>
+static void GenerateDocCommentBody(
+ io::Printer* printer, const DescriptorType* descriptor) {
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ GenerateDocCommentBodyForLocation(printer, location, true, 0);
+ }
+}
+
+static std::string FirstLineOf(const std::string& value) {
+ std::string result = value;
+
+ std::string::size_type pos = result.find_first_of('\n');
+ if (pos != std::string::npos) {
+ result.erase(pos);
+ }
+
+ return result;
+}
+
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+ const Options& options) {
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, message);
+ printer->Print(
+ " * Generated from protobuf message <code>^messagename^</code>\n"
+ " */\n",
+ "fullname", EscapePhpdoc(FullClassName(message, options)),
+ "messagename", EscapePhpdoc(message->full_name()));
+}
+
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+ const Descriptor* message,
+ const Options& options) {
+ // In theory we should have slightly different comments for setters, getters,
+ // etc., but in practice everyone already knows the difference between these
+ // so it's redundant information.
+
+ // We start the comment with the main body based on the comments from the
+ // .proto file (if present). We then end with the field declaration, e.g.:
+ // optional string foo = 5;
+ // If the field is a group, the debug string might end with {.
+ printer->Print("/**\n");
+ printer->Print(" * Constructor.\n");
+ printer->Print(" *\n");
+ printer->Print(" * @param array $data {\n");
+ printer->Print(" * Optional. Data for populating the Message object.\n");
+ printer->Print(" *\n");
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ printer->Print(" * @type ^php_type^ $^var^\n",
+ "php_type", PhpSetterTypeName(field, options),
+ "var", field->name());
+ SourceLocation location;
+ if (field->GetSourceLocation(&location)) {
+ GenerateDocCommentBodyForLocation(printer, location, false, 10);
+ }
+ }
+ printer->Print(" * }\n");
+ printer->Print(" */\n");
+}
+
+void GenerateServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service) {
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, service);
+ printer->Print(
+ " * Protobuf type <code>^fullname^</code>\n"
+ " */\n",
+ "fullname", EscapePhpdoc(service->full_name()));
+}
+
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+ const Options& options, int function_type) {
+ // In theory we should have slightly different comments for setters, getters,
+ // etc., but in practice everyone already knows the difference between these
+ // so it's redundant information.
+
+ // We start the comment with the main body based on the comments from the
+ // .proto file (if present). We then end with the field declaration, e.g.:
+ // optional string foo = 5;
+ // If the field is a group, the debug string might end with {.
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, field);
+ printer->Print(
+ " * Generated from protobuf field <code>^def^</code>\n",
+ "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
+ if (function_type == kFieldSetter) {
+ printer->Print(" * @param ^php_type^ $var\n",
+ "php_type", PhpSetterTypeName(field, options));
+ printer->Print(" * @return $this\n");
+ } else if (function_type == kFieldGetter) {
+ bool can_return_null = field->has_presence() &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+ printer->Print(" * @return ^php_type^^maybe_null^\n",
+ "php_type", PhpGetterTypeName(field, options),
+ "maybe_null", can_return_null ? "|null" : "");
+ }
+ if (field->options().deprecated()) {
+ printer->Print(" * @deprecated\n");
+ }
+ printer->Print(" */\n");
+}
+
+void GenerateWrapperFieldGetterDocComment(io::Printer* printer, const FieldDescriptor* field) {
+ // Generate a doc comment for the special getXXXValue methods that are
+ // generated for wrapper types.
+ const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value");
+ printer->Print("/**\n");
+ printer->Print(
+ " * Returns the unboxed value from <code>get^camel_name^()</code>\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true));
+ GenerateDocCommentBody(printer, field);
+ printer->Print(
+ " * Generated from protobuf field <code>^def^</code>\n",
+ "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
+ printer->Print(" * @return ^php_type^|null\n",
+ "php_type", PhpGetterTypeName(primitiveField, false));
+ printer->Print(" */\n");
+}
+
+void GenerateWrapperFieldSetterDocComment(io::Printer* printer, const FieldDescriptor* field) {
+ // Generate a doc comment for the special setXXXValue methods that are
+ // generated for wrapper types.
+ const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value");
+ printer->Print("/**\n");
+ printer->Print(
+ " * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n",
+ "message_name", FullClassName(field->message_type(), false));
+ GenerateDocCommentBody(printer, field);
+ printer->Print(
+ " * Generated from protobuf field <code>^def^</code>\n",
+ "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
+ printer->Print(" * @param ^php_type^|null $var\n",
+ "php_type", PhpSetterTypeName(primitiveField, false));
+ printer->Print(" * @return $this\n");
+ printer->Print(" */\n");
+}
+
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+ const Options& options) {
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, enum_);
+ printer->Print(
+ " * Protobuf type <code>^fullname^</code>\n"
+ " */\n",
+ "fullname", EscapePhpdoc(enum_->full_name()));
+}
+
+void GenerateEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value) {
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, value);
+ printer->Print(
+ " * Generated from protobuf enum <code>^def^</code>\n"
+ " */\n",
+ "def", EscapePhpdoc(FirstLineOf(value->DebugString())));
+}
+
+void GenerateServiceMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method) {
+ printer->Print("/**\n");
+ GenerateDocCommentBody(printer, method);
+ printer->Print(
+ " * Method <code>^method_name^</code>\n"
+ " *\n",
+ "method_name", EscapePhpdoc(UnderscoresToCamelCase(method->name(), false)));
+ printer->Print(
+ " * @param \\^input_type^ $request\n",
+ "input_type", EscapePhpdoc(FullClassName(method->input_type(), false)));
+ printer->Print(
+ " * @return \\^return_type^\n"
+ " */\n",
+ "return_type", EscapePhpdoc(FullClassName(method->output_type(), false)));
+}
+
+std::string FilenameCName(const FileDescriptor* file) {
+ std::string c_name = file->name();
+ c_name = StringReplace(c_name, ".", "_", true);
+ c_name = StringReplace(c_name, "/", "_", true);
+ return c_name;
+}
+
+void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) {
+ std::string c_name = desc->full_name();
+ c_name = StringReplace(c_name, ".", "_", true);
+ std::string php_name = FullClassName(desc, Options());
+ php_name = StringReplace(php_name, "\\", "\\\\", true);
+ printer->Print(
+ "/* $c_name$ */\n"
+ "\n"
+ "zend_class_entry* $c_name$_ce;\n"
+ "\n"
+ "PHP_METHOD($c_name$, name) {\n"
+ " $file_c_name$_AddDescriptor();\n"
+ " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n"
+ " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n"
+ " const char *name;\n"
+ " zend_long value;\n"
+ " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"l\", &value) ==\n"
+ " FAILURE) {\n"
+ " return;\n"
+ " }\n"
+ " name = upb_enumdef_iton(e, value);\n"
+ " if (!name) {\n"
+ " zend_throw_exception_ex(NULL, 0,\n"
+ " \"$php_name$ has no name \"\n"
+ " \"defined for value \" ZEND_LONG_FMT \".\",\n"
+ " value);\n"
+ " return;\n"
+ " }\n"
+ " RETURN_STRING(name);\n"
+ "}\n"
+ "\n"
+ "PHP_METHOD($c_name$, value) {\n"
+ " $file_c_name$_AddDescriptor();\n"
+ " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n"
+ " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n"
+ " char *name = NULL;\n"
+ " size_t name_len;\n"
+ " int32_t num;\n"
+ " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"s\", &name,\n"
+ " &name_len) == FAILURE) {\n"
+ " return;\n"
+ " }\n"
+ " if (!upb_enumdef_ntoi(e, name, name_len, &num)) {\n"
+ " zend_throw_exception_ex(NULL, 0,\n"
+ " \"$php_name$ has no value \"\n"
+ " \"defined for name %s.\",\n"
+ " name);\n"
+ " return;\n"
+ " }\n"
+ " RETURN_LONG(num);\n"
+ "}\n"
+ "\n"
+ "static zend_function_entry $c_name$_phpmethods[] = {\n"
+ " PHP_ME($c_name$, name, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+ " PHP_ME($c_name$, value, arginfo_lookup, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+ " ZEND_FE_END\n"
+ "};\n"
+ "\n"
+ "static void $c_name$_ModuleInit() {\n"
+ " zend_class_entry tmp_ce;\n"
+ "\n"
+ " INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n"
+ " $c_name$_phpmethods);\n"
+ "\n"
+ " $c_name$_ce = zend_register_internal_class(&tmp_ce);\n",
+ "name", desc->full_name(),
+ "file_c_name", FilenameCName(desc->file()),
+ "c_name", c_name,
+ "php_name", php_name);
+
+ for (int i = 0; i < desc->value_count(); i++) {
+ const EnumValueDescriptor* value = desc->value(i);
+ printer->Print(
+ " zend_declare_class_constant_long($c_name$_ce, \"$name$\",\n"
+ " strlen(\"$name$\"), $num$);\n",
+ "c_name", c_name,
+ "name", value->name(),
+ "num", std::to_string(value->number()));
+ }
+
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+void GenerateCMessage(const Descriptor* message, io::Printer* printer) {
+ std::string c_name = message->full_name();
+ c_name = StringReplace(c_name, ".", "_", true);
+ std::string php_name = FullClassName(message, Options());
+ php_name = StringReplace(php_name, "\\", "\\\\", true);
+ printer->Print(
+ "/* $c_name$ */\n"
+ "\n"
+ "zend_class_entry* $c_name$_ce;\n"
+ "\n"
+ "static PHP_METHOD($c_name$, __construct) {\n"
+ " $file_c_name$_AddDescriptor();\n"
+ " zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n"
+ "}\n"
+ "\n",
+ "file_c_name", FilenameCName(message->file()),
+ "c_name", c_name);
+
+ for (int i = 0; i < message->field_count(); i++) {
+ auto field = message->field(i);
+ printer->Print(
+ "static PHP_METHOD($c_name$, get$camel_name$) {\n"
+ " Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+ " const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n"
+ " \"$name$\");\n"
+ " zval ret;\n"
+ " Message_get(intern, f, &ret);\n"
+ " RETURN_COPY_VALUE(&ret);\n"
+ "}\n"
+ "\n"
+ "static PHP_METHOD($c_name$, set$camel_name$) {\n"
+ " Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+ " const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n"
+ " \"$name$\");\n"
+ " zval *val;\n"
+ " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"z\", &val)\n"
+ " == FAILURE) {\n"
+ " return;\n"
+ " }\n"
+ " Message_set(intern, f, val);\n"
+ " RETURN_COPY(getThis());\n"
+ "}\n"
+ "\n",
+ "c_name", c_name,
+ "name", field->name(),
+ "camel_name", UnderscoresToCamelCase(field->name(), true));
+ }
+
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ auto oneof = message->oneof_decl(i);
+ printer->Print(
+ "static PHP_METHOD($c_name$, get$camel_name$) {\n"
+ " Message* intern = (Message*)Z_OBJ_P(getThis());\n"
+ " const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef,\n"
+ " \"$name$\");\n"
+ " const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof);\n"
+ " RETURN_STRING(field ? upb_fielddef_name(field) : \"\");\n"
+ "}\n",
+ "c_name", c_name,
+ "name", oneof->name(),
+ "camel_name", UnderscoresToCamelCase(oneof->name(), true));
+ }
+
+ switch (message->well_known_type()) {
+ case Descriptor::WELLKNOWNTYPE_ANY:
+ printer->Print(
+ "ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1)\n"
+ " ZEND_ARG_INFO(0, proto)\n"
+ "ZEND_END_ARG_INFO()\n"
+ "\n"
+ );
+ break;
+ case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+ printer->Print(
+ "ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1)\n"
+ " ZEND_ARG_INFO(0, datetime)\n"
+ "ZEND_END_ARG_INFO()\n"
+ "\n"
+ );
+ break;
+ default:
+ break;
+ }
+
+ printer->Print(
+ "static zend_function_entry $c_name$_phpmethods[] = {\n"
+ " PHP_ME($c_name$, __construct, arginfo_construct, ZEND_ACC_PUBLIC)\n",
+ "c_name", c_name);
+
+ for (int i = 0; i < message->field_count(); i++) {
+ auto field = message->field(i);
+ printer->Print(
+ " PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n"
+ " PHP_ME($c_name$, set$camel_name$, arginfo_setter, ZEND_ACC_PUBLIC)\n",
+ "c_name", c_name,
+ "camel_name", UnderscoresToCamelCase(field->name(), true));
+ }
+
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ auto oneof = message->oneof_decl(i);
+ printer->Print(
+ " PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n",
+ "c_name", c_name,
+ "camel_name", UnderscoresToCamelCase(oneof->name(), true));
+ }
+
+ // Extra hand-written functions added to the well-known types.
+ switch (message->well_known_type()) {
+ case Descriptor::WELLKNOWNTYPE_ANY:
+ printer->Print(
+ " PHP_ME($c_name$, is, arginfo_is, ZEND_ACC_PUBLIC)\n"
+ " PHP_ME($c_name$, pack, arginfo_setter, ZEND_ACC_PUBLIC)\n"
+ " PHP_ME($c_name$, unpack, arginfo_void, ZEND_ACC_PUBLIC)\n",
+ "c_name", c_name);
+ break;
+ case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+ printer->Print(
+ " PHP_ME($c_name$, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC)\n"
+ " PHP_ME($c_name$, toDateTime, arginfo_void, ZEND_ACC_PUBLIC)\n",
+ "c_name", c_name);
+ break;
+ default:
+ break;
+ }
+
+ printer->Print(
+ " ZEND_FE_END\n"
+ "};\n"
+ "\n"
+ "static void $c_name$_ModuleInit() {\n"
+ " zend_class_entry tmp_ce;\n"
+ "\n"
+ " INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n"
+ " $c_name$_phpmethods);\n"
+ "\n"
+ " $c_name$_ce = zend_register_internal_class(&tmp_ce);\n"
+ " $c_name$_ce->ce_flags |= ZEND_ACC_FINAL;\n"
+ " $c_name$_ce->create_object = Message_create;\n"
+ " zend_do_inheritance($c_name$_ce, message_ce);\n"
+ "}\n"
+ "\n",
+ "c_name", c_name,
+ "php_name", php_name);
+
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateCMessage(message->nested_type(i), printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateCEnum(message->enum_type(i), printer);
+ }
+}
+
+void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) {
+ std::string c_name = desc->full_name();
+ c_name = StringReplace(c_name, ".", "_", true);
+
+ printer->Print(
+ " $c_name$_ModuleInit();\n",
+ "c_name", c_name);
+}
+
+void GenerateCInit(const Descriptor* message, io::Printer* printer) {
+ std::string c_name = message->full_name();
+ c_name = StringReplace(c_name, ".", "_", true);
+
+ printer->Print(
+ " $c_name$_ModuleInit();\n",
+ "c_name", c_name);
+
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateCInit(message->nested_type(i), printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnumCInit(message->enum_type(i), printer);
+ }
+}
+
+void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files,
+ GeneratorContext* context) {
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ context->Open("../ext/google/protobuf/wkt.inc"));
+ io::Printer printer(output.get(), '$');
+
+ printer.Print(
+ "// This file is generated from the .proto files for the well-known\n"
+ "// types. Do not edit!\n\n");
+
+ printer.Print(
+ "ZEND_BEGIN_ARG_INFO_EX(arginfo_lookup, 0, 0, 1)\n"
+ " ZEND_ARG_INFO(0, key)\n"
+ "ZEND_END_ARG_INFO()\n"
+ "\n"
+ );
+
+ for (auto file : files) {
+ printer.Print(
+ "static void $c_name$_AddDescriptor();\n",
+ "c_name", FilenameCName(file));
+ }
+
+ for (auto file : files) {
+ std::string c_name = FilenameCName(file);
+ std::string metadata_filename = GeneratedMetadataFileName(file, Options());
+ std::string metadata_classname = FilenameToClassname(metadata_filename);
+ std::string metadata_c_name =
+ StringReplace(metadata_classname, "\\", "_", true);
+ metadata_classname = StringReplace(metadata_classname, "\\", "\\\\", true);
+ FileDescriptorProto file_proto;
+ file->CopyTo(&file_proto);
+ std::string serialized;
+ file_proto.SerializeToString(&serialized);
+ printer.Print(
+ "/* $filename$ */\n"
+ "\n"
+ "zend_class_entry* $metadata_c_name$_ce;\n"
+ "\n"
+ "const char $c_name$_descriptor [$size$] = {\n",
+ "filename", file->name(),
+ "c_name", c_name,
+ "metadata_c_name", metadata_c_name,
+ "size", std::to_string(serialized.size()));
+
+ for (size_t i = 0; i < serialized.size();) {
+ for (size_t j = 0; j < 25 && i < serialized.size(); ++i, ++j) {
+ printer.Print("'$ch$', ", "ch", CEscape(serialized.substr(i, 1)));
+ }
+ printer.Print("\n");
+ }
+
+ printer.Print(
+ "};\n"
+ "\n"
+ "static void $c_name$_AddDescriptor() {\n"
+ " if (DescriptorPool_HasFile(\"$filename$\")) return;\n",
+ "filename", file->name(),
+ "c_name", c_name,
+ "metadata_c_name", metadata_c_name);
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ std::string dep_c_name = FilenameCName(file->dependency(i));
+ printer.Print(
+ " $dep_c_name$_AddDescriptor();\n",
+ "dep_c_name", dep_c_name);
+ }
+
+ printer.Print(
+ " DescriptorPool_AddDescriptor(\"$filename$\", $c_name$_descriptor,\n"
+ " sizeof($c_name$_descriptor));\n"
+ "}\n"
+ "\n"
+ "static PHP_METHOD($metadata_c_name$, initOnce) {\n"
+ " $c_name$_AddDescriptor();\n"
+ "}\n"
+ "\n"
+ "static zend_function_entry $metadata_c_name$_methods[] = {\n"
+ " PHP_ME($metadata_c_name$, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+ " ZEND_FE_END\n"
+ "};\n"
+ "\n"
+ "static void $metadata_c_name$_ModuleInit() {\n"
+ " zend_class_entry tmp_ce;\n"
+ "\n"
+ " INIT_CLASS_ENTRY(tmp_ce, \"$metadata_classname$\",\n"
+ " $metadata_c_name$_methods);\n"
+ "\n"
+ " $metadata_c_name$_ce = zend_register_internal_class(&tmp_ce);\n"
+ "}\n"
+ "\n",
+ "filename", file->name(),
+ "c_name", c_name,
+ "metadata_c_name", metadata_c_name,
+ "metadata_classname", metadata_classname);
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateCMessage(file->message_type(i), &printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateCEnum(file->enum_type(i), &printer);
+ }
+ }
+
+ printer.Print(
+ "static void WellKnownTypes_ModuleInit() {\n");
+
+ for (auto file : files) {
+ std::string metadata_filename = GeneratedMetadataFileName(file, Options());
+ std::string metadata_classname = FilenameToClassname(metadata_filename);
+ std::string metadata_c_name =
+ StringReplace(metadata_classname, "\\", "_", true);
+ printer.Print(
+ " $metadata_c_name$_ModuleInit();\n",
+ "metadata_c_name", metadata_c_name);
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateCInit(file->message_type(i), &printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnumCInit(file->enum_type(i), &printer);
+ }
+ }
+
+ printer.Print(
+ "}\n");
+}
+
+} // namespace
+
+std::string GeneratedClassName(const Descriptor* desc) {
+ return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const EnumDescriptor* desc) {
+ return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const ServiceDescriptor* desc) {
+ return GeneratedClassNameImpl(desc);
+}
+
+bool Generator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ return Generate(file, Options(), generator_context, error);
+}
+
+bool Generator::Generate(const FileDescriptor* file, const Options& options,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ if (options.is_descriptor && file->name() != kDescriptorFile) {
+ *error =
+ "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
+ return false;
+ }
+
+ if (!options.is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+ *error =
+ "Can only generate PHP code for proto3 .proto files.\n"
+ "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
+ return false;
+ }
+
+ GenerateFile(file, options, generator_context);
+
+ return true;
+}
+
+bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+ Options options;
+
+ for (const auto& option : Split(parameter, ",", true)) {
+ const std::vector<std::string> option_pair = Split(option, "=", true);
+ if (HasPrefixString(option_pair[0], "aggregate_metadata")) {
+ options.aggregate_metadata = true;
+ for (const auto& prefix : Split(option_pair[1], "#", false)) {
+ options.aggregate_metadata_prefixes.emplace(prefix);
+ GOOGLE_LOG(INFO) << prefix;
+ }
+ } else if (option_pair[0] == "internal") {
+ options.is_descriptor = true;
+ } else if (option_pair[0] == "internal_generate_c_wkt") {
+ GenerateCWellKnownTypes(files, generator_context);
+ } else {
+ GOOGLE_LOG(FATAL) << "Unknown codegen option: " << option_pair[0];
+ }
+ }
+
+ for (auto file : files) {
+ if (!Generate(file, options, generator_context, error)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace php
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.h
new file mode 100644
index 00000000..d3a977aa
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/php/php_generator.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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
+
+#include <compiler/code_generator.h>
+#include <descriptor.h>
+
+#include <string>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+struct Options;
+
+class PROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+ virtual bool Generate(
+ const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+
+ bool GenerateAll(const std::vector<const FileDescriptor*>& files,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override {
+ return FEATURE_PROTO3_OPTIONAL;
+ }
+
+ private:
+ bool Generate(
+ const FileDescriptor* file,
+ const Options& options,
+ GeneratorContext* generator_context,
+ std::string* error) const;
+};
+
+// To skip reserved keywords in php, some generated classname are prefixed.
+// Other code generators may need following API to figure out the actual
+// classname.
+PROTOC_EXPORT std::string GeneratedClassName(const Descriptor* desc);
+PROTOC_EXPORT std::string GeneratedClassName(const EnumDescriptor* desc);
+PROTOC_EXPORT std::string GeneratedClassName(const ServiceDescriptor* desc);
+
+inline bool IsWrapperType(const FieldDescriptor* descriptor) {
+ return descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
+}
+
+} // namespace php
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/plugin.cc b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.cc
new file mode 100644
index 00000000..8ab8dfc8
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.cc
@@ -0,0 +1,200 @@
+// 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)
+
+#include <compiler/plugin.h>
+
+#include <iostream>
+#include <set>
+
+#ifdef _WIN32
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <compiler/plugin.pb.h>
+#include <compiler/code_generator.h>
+#include <io/zero_copy_stream_impl.h>
+#include <descriptor.h>
+#include <io/io_win32.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::io::win32::setmode;
+#endif
+
+class GeneratorResponseContext : public GeneratorContext {
+ public:
+ GeneratorResponseContext(
+ const Version& compiler_version, CodeGeneratorResponse* response,
+ const std::vector<const FileDescriptor*>& parsed_files)
+ : compiler_version_(compiler_version),
+ response_(response),
+ parsed_files_(parsed_files) {}
+ virtual ~GeneratorResponseContext() {}
+
+ // implements GeneratorContext --------------------------------------
+
+ io::ZeroCopyOutputStream* Open(const std::string& filename) override {
+ CodeGeneratorResponse::File* file = response_->add_file();
+ file->set_name(filename);
+ return new io::StringOutputStream(file->mutable_content());
+ }
+
+ io::ZeroCopyOutputStream* OpenForInsert(
+ const std::string& filename,
+ const std::string& insertion_point) override {
+ CodeGeneratorResponse::File* file = response_->add_file();
+ file->set_name(filename);
+ file->set_insertion_point(insertion_point);
+ return new io::StringOutputStream(file->mutable_content());
+ }
+
+ io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo(
+ const std::string& filename, const std::string& insertion_point,
+ const google::protobuf::GeneratedCodeInfo& info) override {
+ CodeGeneratorResponse::File* file = response_->add_file();
+ file->set_name(filename);
+ file->set_insertion_point(insertion_point);
+ *file->mutable_generated_code_info() = info;
+ return new io::StringOutputStream(file->mutable_content());
+ }
+
+ void ListParsedFiles(std::vector<const FileDescriptor*>* output) override {
+ *output = parsed_files_;
+ }
+
+ void GetCompilerVersion(Version* version) const override {
+ *version = compiler_version_;
+ }
+
+ private:
+ Version compiler_version_;
+ CodeGeneratorResponse* response_;
+ const std::vector<const FileDescriptor*>& parsed_files_;
+};
+
+bool GenerateCode(const CodeGeneratorRequest& request,
+ const CodeGenerator& generator,
+ CodeGeneratorResponse* response, std::string* error_msg) {
+ DescriptorPool pool;
+ for (int i = 0; i < request.proto_file_size(); i++) {
+ const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+ if (file == NULL) {
+ // BuildFile() already wrote an error message.
+ return false;
+ }
+ }
+
+ std::vector<const FileDescriptor*> parsed_files;
+ for (int i = 0; i < request.file_to_generate_size(); i++) {
+ parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+ if (parsed_files.back() == NULL) {
+ *error_msg =
+ "protoc asked plugin to generate a file but "
+ "did not provide a descriptor for the file: " +
+ request.file_to_generate(i);
+ return false;
+ }
+ }
+
+ GeneratorResponseContext context(request.compiler_version(), response,
+ parsed_files);
+
+
+ std::string error;
+ bool succeeded = generator.GenerateAll(parsed_files, request.parameter(),
+ &context, &error);
+
+ response->set_supported_features(generator.GetSupportedFeatures());
+
+ if (!succeeded && error.empty()) {
+ error =
+ "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (!error.empty()) {
+ response->set_error(error);
+ }
+
+ return true;
+}
+
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
+
+ if (argc > 1) {
+ std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl;
+ return 1;
+ }
+
+#ifdef _WIN32
+ setmode(STDIN_FILENO, _O_BINARY);
+ setmode(STDOUT_FILENO, _O_BINARY);
+#endif
+
+ CodeGeneratorRequest request;
+ if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
+ std::cerr << argv[0] << ": protoc sent unparseable request to plugin."
+ << std::endl;
+ return 1;
+ }
+
+
+ std::string error_msg;
+ CodeGeneratorResponse response;
+
+ if (GenerateCode(request, *generator, &response, &error_msg)) {
+ if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+ std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+ return 1;
+ }
+ } else {
+ if (!error_msg.empty()) {
+ std::cerr << argv[0] << ": " << error_msg << std::endl;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/plugin.h b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.h
new file mode 100644
index 00000000..24af7aa1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.h
@@ -0,0 +1,95 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Front-end for protoc code generator plugins written in C++.
+//
+// To implement a protoc plugin in C++, simply write an implementation of
+// CodeGenerator, then create a main() function like:
+// int main(int argc, char* argv[]) {
+// MyCodeGenerator generator;
+// return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+// }
+// You must link your plugin against libprotobuf and libprotoc.
+//
+// The core part of PluginMain is to invoke the given CodeGenerator on a
+// CodeGeneratorRequest to generate a CodeGeneratorResponse. This part is
+// abstracted out and made into function GenerateCode so that it can be reused,
+// for example, to implement a variant of PluginMain that does some
+// preprocessing on the input CodeGeneratorRequest before feeding the request
+// to the given code generator.
+//
+// To get protoc to use the plugin, do one of the following:
+// * Place the plugin binary somewhere in the PATH and give it the name
+// "protoc-gen-NAME" (replacing "NAME" with the name of your plugin). If you
+// then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace
+// "NAME" with your plugin's name), protoc will invoke your plugin to generate
+// the output, which will be placed in OUT_DIR.
+// * Place the plugin binary anywhere, with any name, and pass the --plugin
+// parameter to protoc to direct it to your plugin like so:
+// protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR
+// On Windows, make sure to include the .exe suffix:
+// protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+
+#include <string>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class CodeGenerator; // code_generator.h
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
+
+// Implements main() for a protoc plugin exposing the given code generator.
+PROTOC_EXPORT int PluginMain(int argc, char* argv[],
+ const CodeGenerator* generator);
+
+
+// Generates code using the given code generator. Returns true if the code
+// generation is successful. If the code generation fails, error_msg may be
+// populated to describe the failure cause.
+bool GenerateCode(const CodeGeneratorRequest& request,
+ const CodeGenerator& generator,
+ CodeGeneratorResponse* response, std::string* error_msg);
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.cc b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.cc
new file mode 100644
index 00000000..28a197d1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.cc
@@ -0,0 +1,1584 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#include <compiler/plugin.pb.h>
+
+#include <algorithm>
+
+#include <io/coded_stream.h>
+#include <extension_set.h>
+#include <wire_format_lite.h>
+#include <descriptor.h>
+#include <generated_message_reflection.h>
+#include <reflection_ops.h>
+#include <wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <port_def.inc>
+
+PROTOBUF_PRAGMA_INIT_SEG
+PROTOBUF_NAMESPACE_OPEN
+namespace compiler {
+constexpr Version::Version(
+ ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : suffix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , major_(0)
+ , minor_(0)
+ , patch_(0){}
+struct VersionDefaultTypeInternal {
+ constexpr VersionDefaultTypeInternal()
+ : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+ ~VersionDefaultTypeInternal() {}
+ union {
+ Version _instance;
+ };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT VersionDefaultTypeInternal _Version_default_instance_;
+constexpr CodeGeneratorRequest::CodeGeneratorRequest(
+ ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : file_to_generate_()
+ , proto_file_()
+ , parameter_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , compiler_version_(nullptr){}
+struct CodeGeneratorRequestDefaultTypeInternal {
+ constexpr CodeGeneratorRequestDefaultTypeInternal()
+ : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+ ~CodeGeneratorRequestDefaultTypeInternal() {}
+ union {
+ CodeGeneratorRequest _instance;
+ };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+constexpr CodeGeneratorResponse_File::CodeGeneratorResponse_File(
+ ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , insertion_point_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , generated_code_info_(nullptr){}
+struct CodeGeneratorResponse_FileDefaultTypeInternal {
+ constexpr CodeGeneratorResponse_FileDefaultTypeInternal()
+ : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+ ~CodeGeneratorResponse_FileDefaultTypeInternal() {}
+ union {
+ CodeGeneratorResponse_File _instance;
+ };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+constexpr CodeGeneratorResponse::CodeGeneratorResponse(
+ ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+ : file_()
+ , error_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+ , supported_features_(uint64_t{0u}){}
+struct CodeGeneratorResponseDefaultTypeInternal {
+ constexpr CodeGeneratorResponseDefaultTypeInternal()
+ : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+ ~CodeGeneratorResponseDefaultTypeInternal() {}
+ union {
+ CodeGeneratorResponse _instance;
+ };
+};
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
+} // namespace compiler
+PROTOBUF_NAMESPACE_CLOSE
+static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4];
+static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1];
+static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
+
+const uint32_t TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _has_bits_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_),
+ ~0u, // no _extensions_
+ ~0u, // no _oneof_case_
+ ~0u, // no _weak_field_map_
+ ~0u, // no _inlined_string_donated_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, major_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, minor_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, patch_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, suffix_),
+ 1,
+ 2,
+ 3,
+ 0,
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _has_bits_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_),
+ ~0u, // no _extensions_
+ ~0u, // no _oneof_case_
+ ~0u, // no _weak_field_map_
+ ~0u, // no _inlined_string_donated_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, file_to_generate_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, parameter_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, proto_file_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, compiler_version_),
+ ~0u,
+ 0,
+ ~0u,
+ 1,
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _has_bits_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_),
+ ~0u, // no _extensions_
+ ~0u, // no _oneof_case_
+ ~0u, // no _weak_field_map_
+ ~0u, // no _inlined_string_donated_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, name_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, insertion_point_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, content_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, generated_code_info_),
+ 0,
+ 1,
+ 2,
+ 3,
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _has_bits_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_),
+ ~0u, // no _extensions_
+ ~0u, // no _oneof_case_
+ ~0u, // no _weak_field_map_
+ ~0u, // no _inlined_string_donated_
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, error_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, supported_features_),
+ PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, file_),
+ 0,
+ 1,
+ ~0u,
+};
+static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+ { 0, 10, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::Version)},
+ { 14, 24, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)},
+ { 28, 38, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)},
+ { 42, 51, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)},
+};
+
+static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
+ reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_),
+ reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_),
+ reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_),
+ reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_),
+};
+
+const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
+ "\n%google/protobuf/compiler/plugin.proto\022"
+ "\030google.protobuf.compiler\032 google/protob"
+ "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
+ "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s"
+ "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020"
+ "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001("
+ "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf."
+ "FileDescriptorProto\022;\n\020compiler_version\030"
+ "\003 \001(\0132!.google.protobuf.compiler.Version"
+ "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001("
+ "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 "
+ "\003(\01324.google.protobuf.compiler.CodeGener"
+ "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022"
+ "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001("
+ "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google."
+ "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n"
+ "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION"
+ "AL\020\001BW\n\034com.google.protobuf.compilerB\014Pl"
+ "uginProtosZ)google.golang.org/protobuf/t"
+ "ypes/pluginpb"
+ ;
+static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
+ &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
+};
+static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
+const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
+ false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto",
+ &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4,
+ schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets,
+ file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+};
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter() {
+ return &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+PROTOBUF_NAMESPACE_OPEN
+namespace compiler {
+const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor() {
+ ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+ return file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0];
+}
+bool CodeGeneratorResponse_Feature_IsValid(int value) {
+ switch (value) {
+ case 0:
+ case 1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_NONE;
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL;
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MIN;
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MAX;
+constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE;
+#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+// ===================================================================
+
+class Version::_Internal {
+ public:
+ using HasBits = decltype(std::declval<Version>()._has_bits_);
+ static void set_has_major(HasBits* has_bits) {
+ (*has_bits)[0] |= 2u;
+ }
+ static void set_has_minor(HasBits* has_bits) {
+ (*has_bits)[0] |= 4u;
+ }
+ static void set_has_patch(HasBits* has_bits) {
+ (*has_bits)[0] |= 8u;
+ }
+ static void set_has_suffix(HasBits* has_bits) {
+ (*has_bits)[0] |= 1u;
+ }
+};
+
+Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
+ SharedCtor();
+ if (!is_message_owned) {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.Version)
+}
+Version::Version(const Version& from)
+ : ::PROTOBUF_NAMESPACE_ID::Message(),
+ _has_bits_(from._has_bits_) {
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+ suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_suffix()) {
+ suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_suffix(),
+ GetArenaForAllocation());
+ }
+ ::memcpy(&major_, &from.major_,
+ static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+ reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version)
+}
+
+inline void Version::SharedCtor() {
+suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+ reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
+ 0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+ reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+}
+
+Version::~Version() {
+ // @@protoc_insertion_point(destructor:google.protobuf.compiler.Version)
+ if (GetArenaForAllocation() != nullptr) return;
+ SharedDtor();
+ _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+inline void Version::SharedDtor() {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ suffix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+}
+
+void Version::ArenaDtor(void* object) {
+ Version* _this = reinterpret_cast< Version* >(object);
+ (void)_this;
+}
+void Version::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void Version::SetCachedSize(int size) const {
+ _cached_size_.Set(size);
+}
+
+void Version::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000001u) {
+ suffix_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x0000000eu) {
+ ::memset(&major_, 0, static_cast<size_t>(
+ reinterpret_cast<char*>(&patch_) -
+ reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+ }
+ _has_bits_.Clear();
+ _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* Version::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+ _Internal::HasBits has_bits{};
+ while (!ctx->Done(&ptr)) {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3) {
+ // optional int32 major = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+ _Internal::set_has_major(&has_bits);
+ major_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional int32 minor = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+ _Internal::set_has_minor(&has_bits);
+ minor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional int32 patch = 3;
+ case 3:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+ _Internal::set_has_patch(&has_bits);
+ patch_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional string suffix = 4;
+ case 4:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+ auto str = _internal_mutable_suffix();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.Version.suffix");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4)) {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(
+ tag,
+ _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+ ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+message_done:
+ _has_bits_.Or(has_bits);
+ return ptr;
+failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+}
+
+uint8_t* Version::_InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version)
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ // optional int32 major = 1;
+ if (cached_has_bits & 0x00000002u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_major(), target);
+ }
+
+ // optional int32 minor = 2;
+ if (cached_has_bits & 0x00000004u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_minor(), target);
+ }
+
+ // optional int32 patch = 3;
+ if (cached_has_bits & 0x00000008u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_patch(), target);
+ }
+
+ // optional string suffix = 4;
+ if (cached_has_bits & 0x00000001u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_suffix().data(), static_cast<int>(this->_internal_suffix().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.Version.suffix");
+ target = stream->WriteStringMaybeAliased(
+ 4, this->_internal_suffix(), target);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+ _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version)
+ return target;
+}
+
+size_t Version::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x0000000fu) {
+ // optional string suffix = 4;
+ if (cached_has_bits & 0x00000001u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_suffix());
+ }
+
+ // optional int32 major = 1;
+ if (cached_has_bits & 0x00000002u) {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_major());
+ }
+
+ // optional int32 minor = 2;
+ if (cached_has_bits & 0x00000004u) {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_minor());
+ }
+
+ // optional int32 patch = 3;
+ if (cached_has_bits & 0x00000008u) {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32SizePlusOne(this->_internal_patch());
+ }
+
+ }
+ return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Version::_class_data_ = {
+ ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+ Version::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Version::GetClassData() const { return &_class_data_; }
+
+void Version::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
+ const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+ static_cast<Version *>(to)->MergeFrom(
+ static_cast<const Version &>(from));
+}
+
+
+void Version::MergeFrom(const Version& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ cached_has_bits = from._has_bits_[0];
+ if (cached_has_bits & 0x0000000fu) {
+ if (cached_has_bits & 0x00000001u) {
+ _internal_set_suffix(from._internal_suffix());
+ }
+ if (cached_has_bits & 0x00000002u) {
+ major_ = from.major_;
+ }
+ if (cached_has_bits & 0x00000004u) {
+ minor_ = from.minor_;
+ }
+ if (cached_has_bits & 0x00000008u) {
+ patch_ = from.patch_;
+ }
+ _has_bits_[0] |= cached_has_bits;
+ }
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void Version::CopyFrom(const Version& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.Version)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Version::IsInitialized() const {
+ return true;
+}
+
+void Version::InternalSwap(Version* other) {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ swap(_has_bits_[0], other->_has_bits_[0]);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &suffix_, lhs_arena,
+ &other->suffix_, rhs_arena
+ );
+ ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+ PROTOBUF_FIELD_OFFSET(Version, patch_)
+ + sizeof(Version::patch_)
+ - PROTOBUF_FIELD_OFFSET(Version, major_)>(
+ reinterpret_cast<char*>(&major_),
+ reinterpret_cast<char*>(&other->major_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata Version::GetMetadata() const {
+ return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+ &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+ file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0]);
+}
+
+// ===================================================================
+
+class CodeGeneratorRequest::_Internal {
+ public:
+ using HasBits = decltype(std::declval<CodeGeneratorRequest>()._has_bits_);
+ static void set_has_parameter(HasBits* has_bits) {
+ (*has_bits)[0] |= 1u;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version(const CodeGeneratorRequest* msg);
+ static void set_has_compiler_version(HasBits* has_bits) {
+ (*has_bits)[0] |= 2u;
+ }
+};
+
+const ::PROTOBUF_NAMESPACE_ID::compiler::Version&
+CodeGeneratorRequest::_Internal::compiler_version(const CodeGeneratorRequest* msg) {
+ return *msg->compiler_version_;
+}
+void CodeGeneratorRequest::clear_proto_file() {
+ proto_file_.Clear();
+}
+CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
+ file_to_generate_(arena),
+ proto_file_(arena) {
+ SharedCtor();
+ if (!is_message_owned) {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
+ : ::PROTOBUF_NAMESPACE_ID::Message(),
+ _has_bits_(from._has_bits_),
+ file_to_generate_(from.file_to_generate_),
+ proto_file_(from.proto_file_) {
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+ parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_parameter()) {
+ parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_parameter(),
+ GetArenaForAllocation());
+ }
+ if (from._internal_has_compiler_version()) {
+ compiler_version_ = new ::PROTOBUF_NAMESPACE_ID::compiler::Version(*from.compiler_version_);
+ } else {
+ compiler_version_ = nullptr;
+ }
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
+inline void CodeGeneratorRequest::SharedCtor() {
+parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+compiler_version_ = nullptr;
+}
+
+CodeGeneratorRequest::~CodeGeneratorRequest() {
+ // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest)
+ if (GetArenaForAllocation() != nullptr) return;
+ SharedDtor();
+ _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+inline void CodeGeneratorRequest::SharedDtor() {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ parameter_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ if (this != internal_default_instance()) delete compiler_version_;
+}
+
+void CodeGeneratorRequest::ArenaDtor(void* object) {
+ CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object);
+ (void)_this;
+}
+void CodeGeneratorRequest::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void CodeGeneratorRequest::SetCachedSize(int size) const {
+ _cached_size_.Set(size);
+}
+
+void CodeGeneratorRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ file_to_generate_.Clear();
+ proto_file_.Clear();
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000003u) {
+ if (cached_has_bits & 0x00000001u) {
+ parameter_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x00000002u) {
+ GOOGLE_DCHECK(compiler_version_ != nullptr);
+ compiler_version_->Clear();
+ }
+ }
+ _has_bits_.Clear();
+ _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+ _Internal::HasBits has_bits{};
+ while (!ctx->Done(&ptr)) {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3) {
+ // repeated string file_to_generate = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+ ptr -= 1;
+ do {
+ ptr += 1;
+ auto str = _internal_add_file_to_generate();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ if (!ctx->DataAvailable(ptr)) break;
+ } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
+ } else
+ goto handle_unusual;
+ continue;
+ // optional string parameter = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+ auto str = _internal_mutable_parameter();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.parameter");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional .google.protobuf.compiler.Version compiler_version = 3;
+ case 3:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+ ptr = ctx->ParseMessage(_internal_mutable_compiler_version(), ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ case 15:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+ ptr -= 1;
+ do {
+ ptr += 1;
+ ptr = ctx->ParseMessage(_internal_add_proto_file(), ptr);
+ CHK_(ptr);
+ if (!ctx->DataAvailable(ptr)) break;
+ } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
+ } else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4)) {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(
+ tag,
+ _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+ ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+message_done:
+ _has_bits_.Or(has_bits);
+ return ptr;
+failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+}
+
+uint8_t* CodeGeneratorRequest::_InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ // repeated string file_to_generate = 1;
+ for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; i++) {
+ const auto& s = this->_internal_file_to_generate(i);
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ s.data(), static_cast<int>(s.length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
+ target = stream->WriteString(1, s, target);
+ }
+
+ cached_has_bits = _has_bits_[0];
+ // optional string parameter = 2;
+ if (cached_has_bits & 0x00000001u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_parameter().data(), static_cast<int>(this->_internal_parameter().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
+ target = stream->WriteStringMaybeAliased(
+ 2, this->_internal_parameter(), target);
+ }
+
+ // optional .google.protobuf.compiler.Version compiler_version = 3;
+ if (cached_has_bits & 0x00000002u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+ InternalWriteMessage(
+ 3, _Internal::compiler_version(this), target, stream);
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ for (unsigned int i = 0,
+ n = static_cast<unsigned int>(this->_internal_proto_file_size()); i < n; i++) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+ InternalWriteMessage(15, this->_internal_proto_file(i), target, stream);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+ _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest)
+ return target;
+}
+
+size_t CodeGeneratorRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ // repeated string file_to_generate = 1;
+ total_size += 1 *
+ ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(file_to_generate_.size());
+ for (int i = 0, n = file_to_generate_.size(); i < n; i++) {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ file_to_generate_.Get(i));
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ total_size += 1UL * this->_internal_proto_file_size();
+ for (const auto& msg : this->proto_file_) {
+ total_size +=
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
+ }
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000003u) {
+ // optional string parameter = 2;
+ if (cached_has_bits & 0x00000001u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_parameter());
+ }
+
+ // optional .google.protobuf.compiler.Version compiler_version = 3;
+ if (cached_has_bits & 0x00000002u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+ *compiler_version_);
+ }
+
+ }
+ return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorRequest::_class_data_ = {
+ ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+ CodeGeneratorRequest::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorRequest::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorRequest::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
+ const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+ static_cast<CodeGeneratorRequest *>(to)->MergeFrom(
+ static_cast<const CodeGeneratorRequest &>(from));
+}
+
+
+void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ file_to_generate_.MergeFrom(from.file_to_generate_);
+ proto_file_.MergeFrom(from.proto_file_);
+ cached_has_bits = from._has_bits_[0];
+ if (cached_has_bits & 0x00000003u) {
+ if (cached_has_bits & 0x00000001u) {
+ _internal_set_parameter(from._internal_parameter());
+ }
+ if (cached_has_bits & 0x00000002u) {
+ _internal_mutable_compiler_version()->::PROTOBUF_NAMESPACE_ID::compiler::Version::MergeFrom(from._internal_compiler_version());
+ }
+ }
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorRequest::IsInitialized() const {
+ if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(proto_file_))
+ return false;
+ return true;
+}
+
+void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ swap(_has_bits_[0], other->_has_bits_[0]);
+ file_to_generate_.InternalSwap(&other->file_to_generate_);
+ proto_file_.InternalSwap(&other->proto_file_);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &parameter_, lhs_arena,
+ &other->parameter_, rhs_arena
+ );
+ swap(compiler_version_, other->compiler_version_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorRequest::GetMetadata() const {
+ return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+ &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+ file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]);
+}
+
+// ===================================================================
+
+class CodeGeneratorResponse_File::_Internal {
+ public:
+ using HasBits = decltype(std::declval<CodeGeneratorResponse_File>()._has_bits_);
+ static void set_has_name(HasBits* has_bits) {
+ (*has_bits)[0] |= 1u;
+ }
+ static void set_has_insertion_point(HasBits* has_bits) {
+ (*has_bits)[0] |= 2u;
+ }
+ static void set_has_content(HasBits* has_bits) {
+ (*has_bits)[0] |= 4u;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info(const CodeGeneratorResponse_File* msg);
+ static void set_has_generated_code_info(HasBits* has_bits) {
+ (*has_bits)[0] |= 8u;
+ }
+};
+
+const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&
+CodeGeneratorResponse_File::_Internal::generated_code_info(const CodeGeneratorResponse_File* msg) {
+ return *msg->generated_code_info_;
+}
+void CodeGeneratorResponse_File::clear_generated_code_info() {
+ if (generated_code_info_ != nullptr) generated_code_info_->Clear();
+ _has_bits_[0] &= ~0x00000008u;
+}
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) {
+ SharedCtor();
+ if (!is_message_owned) {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
+ : ::PROTOBUF_NAMESPACE_ID::Message(),
+ _has_bits_(from._has_bits_) {
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+ name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_name()) {
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(),
+ GetArenaForAllocation());
+ }
+ insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_insertion_point()) {
+ insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_insertion_point(),
+ GetArenaForAllocation());
+ }
+ content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_content()) {
+ content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(),
+ GetArenaForAllocation());
+ }
+ if (from._internal_has_generated_code_info()) {
+ generated_code_info_ = new ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from.generated_code_info_);
+ } else {
+ generated_code_info_ = nullptr;
+ }
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
+inline void CodeGeneratorResponse_File::SharedCtor() {
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+generated_code_info_ = nullptr;
+}
+
+CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
+ // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+ if (GetArenaForAllocation() != nullptr) return;
+ SharedDtor();
+ _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+inline void CodeGeneratorResponse_File::SharedDtor() {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ insertion_point_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ if (this != internal_default_instance()) delete generated_code_info_;
+}
+
+void CodeGeneratorResponse_File::ArenaDtor(void* object) {
+ CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse_File::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void CodeGeneratorResponse_File::SetCachedSize(int size) const {
+ _cached_size_.Set(size);
+}
+
+void CodeGeneratorResponse_File::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x0000000fu) {
+ if (cached_has_bits & 0x00000001u) {
+ name_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x00000002u) {
+ insertion_point_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x00000004u) {
+ content_.ClearNonDefaultToEmpty();
+ }
+ if (cached_has_bits & 0x00000008u) {
+ GOOGLE_DCHECK(generated_code_info_ != nullptr);
+ generated_code_info_->Clear();
+ }
+ }
+ _has_bits_.Clear();
+ _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+ _Internal::HasBits has_bits{};
+ while (!ctx->Done(&ptr)) {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3) {
+ // optional string name = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+ auto str = _internal_mutable_name();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.name");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional string insertion_point = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+ auto str = _internal_mutable_insertion_point();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional string content = 15;
+ case 15:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+ auto str = _internal_mutable_content();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.content");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+ case 16:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 130)) {
+ ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4)) {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(
+ tag,
+ _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+ ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+message_done:
+ _has_bits_.Or(has_bits);
+ return ptr;
+failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+}
+
+uint8_t* CodeGeneratorResponse_File::_InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ // optional string name = 1;
+ if (cached_has_bits & 0x00000001u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
+ target = stream->WriteStringMaybeAliased(
+ 1, this->_internal_name(), target);
+ }
+
+ // optional string insertion_point = 2;
+ if (cached_has_bits & 0x00000002u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_insertion_point().data(), static_cast<int>(this->_internal_insertion_point().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
+ target = stream->WriteStringMaybeAliased(
+ 2, this->_internal_insertion_point(), target);
+ }
+
+ // optional string content = 15;
+ if (cached_has_bits & 0x00000004u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_content().data(), static_cast<int>(this->_internal_content().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
+ target = stream->WriteStringMaybeAliased(
+ 15, this->_internal_content(), target);
+ }
+
+ // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+ if (cached_has_bits & 0x00000008u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+ InternalWriteMessage(
+ 16, _Internal::generated_code_info(this), target, stream);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+ _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File)
+ return target;
+}
+
+size_t CodeGeneratorResponse_File::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x0000000fu) {
+ // optional string name = 1;
+ if (cached_has_bits & 0x00000001u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_name());
+ }
+
+ // optional string insertion_point = 2;
+ if (cached_has_bits & 0x00000002u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_insertion_point());
+ }
+
+ // optional string content = 15;
+ if (cached_has_bits & 0x00000004u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_content());
+ }
+
+ // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+ if (cached_has_bits & 0x00000008u) {
+ total_size += 2 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+ *generated_code_info_);
+ }
+
+ }
+ return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorResponse_File::_class_data_ = {
+ ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+ CodeGeneratorResponse_File::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorResponse_File::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorResponse_File::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
+ const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+ static_cast<CodeGeneratorResponse_File *>(to)->MergeFrom(
+ static_cast<const CodeGeneratorResponse_File &>(from));
+}
+
+
+void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ cached_has_bits = from._has_bits_[0];
+ if (cached_has_bits & 0x0000000fu) {
+ if (cached_has_bits & 0x00000001u) {
+ _internal_set_name(from._internal_name());
+ }
+ if (cached_has_bits & 0x00000002u) {
+ _internal_set_insertion_point(from._internal_insertion_point());
+ }
+ if (cached_has_bits & 0x00000004u) {
+ _internal_set_content(from._internal_content());
+ }
+ if (cached_has_bits & 0x00000008u) {
+ _internal_mutable_generated_code_info()->::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::MergeFrom(from._internal_generated_code_info());
+ }
+ }
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorResponse_File::IsInitialized() const {
+ return true;
+}
+
+void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ swap(_has_bits_[0], other->_has_bits_[0]);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &name_, lhs_arena,
+ &other->name_, rhs_arena
+ );
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &insertion_point_, lhs_arena,
+ &other->insertion_point_, rhs_arena
+ );
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &content_, lhs_arena,
+ &other->content_, rhs_arena
+ );
+ swap(generated_code_info_, other->generated_code_info_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const {
+ return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+ &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+ file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[2]);
+}
+
+// ===================================================================
+
+class CodeGeneratorResponse::_Internal {
+ public:
+ using HasBits = decltype(std::declval<CodeGeneratorResponse>()._has_bits_);
+ static void set_has_error(HasBits* has_bits) {
+ (*has_bits)[0] |= 1u;
+ }
+ static void set_has_supported_features(HasBits* has_bits) {
+ (*has_bits)[0] |= 2u;
+ }
+};
+
+CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned)
+ : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned),
+ file_(arena) {
+ SharedCtor();
+ if (!is_message_owned) {
+ RegisterArenaDtor(arena);
+ }
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
+ : ::PROTOBUF_NAMESPACE_ID::Message(),
+ _has_bits_(from._has_bits_),
+ file_(from.file_) {
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+ error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (from._internal_has_error()) {
+ error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_error(),
+ GetArenaForAllocation());
+ }
+ supported_features_ = from.supported_features_;
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
+inline void CodeGeneratorResponse::SharedCtor() {
+error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+supported_features_ = uint64_t{0u};
+}
+
+CodeGeneratorResponse::~CodeGeneratorResponse() {
+ // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse)
+ if (GetArenaForAllocation() != nullptr) return;
+ SharedDtor();
+ _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+inline void CodeGeneratorResponse::SharedDtor() {
+ GOOGLE_DCHECK(GetArenaForAllocation() == nullptr);
+ error_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+}
+
+void CodeGeneratorResponse::ArenaDtor(void* object) {
+ CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void CodeGeneratorResponse::SetCachedSize(int size) const {
+ _cached_size_.Set(size);
+}
+
+void CodeGeneratorResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ file_.Clear();
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000001u) {
+ error_.ClearNonDefaultToEmpty();
+ }
+ supported_features_ = uint64_t{0u};
+ _has_bits_.Clear();
+ _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+ _Internal::HasBits has_bits{};
+ while (!ctx->Done(&ptr)) {
+ uint32_t tag;
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+ switch (tag >> 3) {
+ // optional string error = 1;
+ case 1:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+ auto str = _internal_mutable_error();
+ ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+ #ifndef NDEBUG
+ ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.error");
+ #endif // !NDEBUG
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // optional uint64 supported_features = 2;
+ case 2:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+ _Internal::set_has_supported_features(&has_bits);
+ supported_features_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+ CHK_(ptr);
+ } else
+ goto handle_unusual;
+ continue;
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ case 15:
+ if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+ ptr -= 1;
+ do {
+ ptr += 1;
+ ptr = ctx->ParseMessage(_internal_add_file(), ptr);
+ CHK_(ptr);
+ if (!ctx->DataAvailable(ptr)) break;
+ } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
+ } else
+ goto handle_unusual;
+ continue;
+ default:
+ goto handle_unusual;
+ } // switch
+ handle_unusual:
+ if ((tag == 0) || ((tag & 7) == 4)) {
+ CHK_(ptr);
+ ctx->SetLastTag(tag);
+ goto message_done;
+ }
+ ptr = UnknownFieldParse(
+ tag,
+ _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+ ptr, ctx);
+ CHK_(ptr != nullptr);
+ } // while
+message_done:
+ _has_bits_.Or(has_bits);
+ return ptr;
+failure:
+ ptr = nullptr;
+ goto message_done;
+#undef CHK_
+}
+
+uint8_t* CodeGeneratorResponse::_InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ cached_has_bits = _has_bits_[0];
+ // optional string error = 1;
+ if (cached_has_bits & 0x00000001u) {
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->_internal_error().data(), static_cast<int>(this->_internal_error().length()),
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
+ target = stream->WriteStringMaybeAliased(
+ 1, this->_internal_error(), target);
+ }
+
+ // optional uint64 supported_features = 2;
+ if (cached_has_bits & 0x00000002u) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->_internal_supported_features(), target);
+ }
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ for (unsigned int i = 0,
+ n = static_cast<unsigned int>(this->_internal_file_size()); i < n; i++) {
+ target = stream->EnsureSpace(target);
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+ InternalWriteMessage(15, this->_internal_file(i), target, stream);
+ }
+
+ if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+ target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+ _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse)
+ return target;
+}
+
+size_t CodeGeneratorResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
+ size_t total_size = 0;
+
+ uint32_t cached_has_bits = 0;
+ // Prevent compiler warnings about cached_has_bits being unused
+ (void) cached_has_bits;
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ total_size += 1UL * this->_internal_file_size();
+ for (const auto& msg : this->file_) {
+ total_size +=
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
+ }
+
+ cached_has_bits = _has_bits_[0];
+ if (cached_has_bits & 0x00000003u) {
+ // optional string error = 1;
+ if (cached_has_bits & 0x00000001u) {
+ total_size += 1 +
+ ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+ this->_internal_error());
+ }
+
+ // optional uint64 supported_features = 2;
+ if (cached_has_bits & 0x00000002u) {
+ total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64SizePlusOne(this->_internal_supported_features());
+ }
+
+ }
+ return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);
+}
+
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData CodeGeneratorResponse::_class_data_ = {
+ ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck,
+ CodeGeneratorResponse::MergeImpl
+};
+const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*CodeGeneratorResponse::GetClassData() const { return &_class_data_; }
+
+void CodeGeneratorResponse::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to,
+ const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+ static_cast<CodeGeneratorResponse *>(to)->MergeFrom(
+ static_cast<const CodeGeneratorResponse &>(from));
+}
+
+
+void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+ GOOGLE_DCHECK_NE(&from, this);
+ uint32_t cached_has_bits = 0;
+ (void) cached_has_bits;
+
+ file_.MergeFrom(from.file_);
+ cached_has_bits = from._has_bits_[0];
+ if (cached_has_bits & 0x00000003u) {
+ if (cached_has_bits & 0x00000001u) {
+ _internal_set_error(from._internal_error());
+ }
+ if (cached_has_bits & 0x00000002u) {
+ supported_features_ = from.supported_features_;
+ }
+ _has_bits_[0] |= cached_has_bits;
+ }
+ _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+}
+
+void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorResponse::IsInitialized() const {
+ return true;
+}
+
+void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
+ using std::swap;
+ auto* lhs_arena = GetArenaForAllocation();
+ auto* rhs_arena = other->GetArenaForAllocation();
+ _internal_metadata_.InternalSwap(&other->_internal_metadata_);
+ swap(_has_bits_[0], other->_has_bits_[0]);
+ file_.InternalSwap(&other->file_);
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+ &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
+ &error_, lhs_arena,
+ &other->error_, rhs_arena
+ );
+ swap(supported_features_, other->supported_features_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse::GetMetadata() const {
+ return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+ &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+ file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[3]);
+}
+
+// @@protoc_insertion_point(namespace_scope)
+} // namespace compiler
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::compiler::Version >(Arena* arena) {
+ return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::Version >(arena);
+}
+template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest >(Arena* arena) {
+ return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >(Arena* arena) {
+ return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >(arena);
+}
+template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(Arena* arena) {
+ return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+#include <port_undef.inc>
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.h b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.h
new file mode 100644
index 00000000..a3ed430b
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.pb.h
@@ -0,0 +1,1909 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+
+#include <limits>
+#include <string>
+
+#include <port_def.inc>
+#if PROTOBUF_VERSION < 3019000
+#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 3019004 < 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 <port_undef.inc>
+#include <io/coded_stream.h>
+#include <arena.h>
+#include <arenastring.h>
+#include <generated_message_table_driven.h>
+#include <generated_message_util.h>
+#include <metadata_lite.h>
+#include <generated_message_reflection.h>
+#include <message.h>
+#include <repeated_field.h> // IWYU pragma: export
+#include <extension_set.h> // IWYU pragma: export
+#include <generated_enum_reflection.h>
+#include <unknown_field_set.h>
+#include <descriptor.pb.h>
+// @@protoc_insertion_point(includes)
+#include <port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+PROTOBUF_NAMESPACE_OPEN
+namespace internal {
+class AnyMetadata;
+} // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4]
+ PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+ static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
+ static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
+ static const uint32_t offsets[];
+};
+PROTOC_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+PROTOBUF_NAMESPACE_OPEN
+namespace compiler {
+class CodeGeneratorRequest;
+struct CodeGeneratorRequestDefaultTypeInternal;
+PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+class CodeGeneratorResponse;
+struct CodeGeneratorResponseDefaultTypeInternal;
+PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
+class CodeGeneratorResponse_File;
+struct CodeGeneratorResponse_FileDefaultTypeInternal;
+PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+class Version;
+struct VersionDefaultTypeInternal;
+PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
+} // namespace compiler
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest>(Arena*);
+template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse>(Arena*);
+template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File>(Arena*);
+template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+PROTOBUF_NAMESPACE_OPEN
+namespace compiler {
+
+enum CodeGeneratorResponse_Feature : int {
+ CodeGeneratorResponse_Feature_FEATURE_NONE = 0,
+ CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1
+};
+PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value);
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = CodeGeneratorResponse_Feature_FEATURE_NONE;
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL;
+constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_MAX + 1;
+
+PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor();
+template<typename T>
+inline const std::string& CodeGeneratorResponse_Feature_Name(T enum_t_value) {
+ static_assert(::std::is_same<T, CodeGeneratorResponse_Feature>::value ||
+ ::std::is_integral<T>::value,
+ "Incorrect type passed to function CodeGeneratorResponse_Feature_Name.");
+ return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
+ CodeGeneratorResponse_Feature_descriptor(), enum_t_value);
+}
+inline bool CodeGeneratorResponse_Feature_Parse(
+ ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) {
+ return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<CodeGeneratorResponse_Feature>(
+ CodeGeneratorResponse_Feature_descriptor(), name, value);
+}
+// ===================================================================
+
+class PROTOC_EXPORT Version final :
+ public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
+ public:
+ inline Version() : Version(nullptr) {}
+ ~Version() override;
+ explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ Version(const Version& from);
+ Version(Version&& from) noexcept
+ : Version() {
+ *this = ::std::move(from);
+ }
+
+ inline Version& operator=(const Version& from) {
+ CopyFrom(from);
+ return *this;
+ }
+ inline Version& operator=(Version&& from) noexcept {
+ if (this == &from) return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+ #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+ #endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ ) {
+ InternalSwap(&from);
+ } else {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+ }
+ inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+ }
+
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+ return GetDescriptor();
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+ return default_instance().GetMetadata().descriptor;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+ return default_instance().GetMetadata().reflection;
+ }
+ static const Version& default_instance() {
+ return *internal_default_instance();
+ }
+ static inline const Version* internal_default_instance() {
+ return reinterpret_cast<const Version*>(
+ &_Version_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages =
+ 0;
+
+ friend void swap(Version& a, Version& b) {
+ a.Swap(&b);
+ }
+ inline void Swap(Version* other) {
+ if (other == this) return;
+ #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr &&
+ GetOwningArena() == other->GetOwningArena()) {
+ #else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena()) {
+ #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ } else {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(Version* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ Version* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+ return CreateMaybeMessage<Version>(arena);
+ }
+ using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+ void CopyFrom(const Version& from);
+ using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+ void MergeFrom(const Version& from);
+ private:
+ static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
+ public:
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final { return _cached_size_.Get(); }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const final;
+ void InternalSwap(Version* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+ return "google.protobuf.compiler.Version";
+ }
+ protected:
+ explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned = false);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+ public:
+
+ static const ClassData _class_data_;
+ const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+ ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ enum : int {
+ kSuffixFieldNumber = 4,
+ kMajorFieldNumber = 1,
+ kMinorFieldNumber = 2,
+ kPatchFieldNumber = 3,
+ };
+ // optional string suffix = 4;
+ bool has_suffix() const;
+ private:
+ bool _internal_has_suffix() const;
+ public:
+ void clear_suffix();
+ const std::string& suffix() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_suffix(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_suffix();
+ PROTOBUF_NODISCARD std::string* release_suffix();
+ void set_allocated_suffix(std::string* suffix);
+ private:
+ const std::string& _internal_suffix() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_suffix(const std::string& value);
+ std::string* _internal_mutable_suffix();
+ public:
+
+ // optional int32 major = 1;
+ bool has_major() const;
+ private:
+ bool _internal_has_major() const;
+ public:
+ void clear_major();
+ int32_t major() const;
+ void set_major(int32_t value);
+ private:
+ int32_t _internal_major() const;
+ void _internal_set_major(int32_t value);
+ public:
+
+ // optional int32 minor = 2;
+ bool has_minor() const;
+ private:
+ bool _internal_has_minor() const;
+ public:
+ void clear_minor();
+ int32_t minor() const;
+ void set_minor(int32_t value);
+ private:
+ int32_t _internal_minor() const;
+ void _internal_set_minor(int32_t value);
+ public:
+
+ // optional int32 patch = 3;
+ bool has_patch() const;
+ private:
+ bool _internal_has_patch() const;
+ public:
+ void clear_patch();
+ int32_t patch() const;
+ void set_patch(int32_t value);
+ private:
+ int32_t _internal_patch() const;
+ void _internal_set_patch(int32_t value);
+ public:
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version)
+ private:
+ class _Internal;
+
+ template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr suffix_;
+ int32_t major_;
+ int32_t minor_;
+ int32_t patch_;
+ friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PROTOC_EXPORT CodeGeneratorRequest final :
+ public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ {
+ public:
+ inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {}
+ ~CodeGeneratorRequest() override;
+ explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ CodeGeneratorRequest(const CodeGeneratorRequest& from);
+ CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
+ : CodeGeneratorRequest() {
+ *this = ::std::move(from);
+ }
+
+ inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
+ CopyFrom(from);
+ return *this;
+ }
+ inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept {
+ if (this == &from) return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+ #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+ #endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ ) {
+ InternalSwap(&from);
+ } else {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+ }
+ inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+ }
+
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+ return GetDescriptor();
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+ return default_instance().GetMetadata().descriptor;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+ return default_instance().GetMetadata().reflection;
+ }
+ static const CodeGeneratorRequest& default_instance() {
+ return *internal_default_instance();
+ }
+ static inline const CodeGeneratorRequest* internal_default_instance() {
+ return reinterpret_cast<const CodeGeneratorRequest*>(
+ &_CodeGeneratorRequest_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages =
+ 1;
+
+ friend void swap(CodeGeneratorRequest& a, CodeGeneratorRequest& b) {
+ a.Swap(&b);
+ }
+ inline void Swap(CodeGeneratorRequest* other) {
+ if (other == this) return;
+ #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr &&
+ GetOwningArena() == other->GetOwningArena()) {
+ #else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena()) {
+ #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ } else {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(CodeGeneratorRequest* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+ return CreateMaybeMessage<CodeGeneratorRequest>(arena);
+ }
+ using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+ void CopyFrom(const CodeGeneratorRequest& from);
+ using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+ void MergeFrom(const CodeGeneratorRequest& from);
+ private:
+ static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
+ public:
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final { return _cached_size_.Get(); }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const final;
+ void InternalSwap(CodeGeneratorRequest* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+ return "google.protobuf.compiler.CodeGeneratorRequest";
+ }
+ protected:
+ explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned = false);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+ public:
+
+ static const ClassData _class_data_;
+ const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+ ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ enum : int {
+ kFileToGenerateFieldNumber = 1,
+ kProtoFileFieldNumber = 15,
+ kParameterFieldNumber = 2,
+ kCompilerVersionFieldNumber = 3,
+ };
+ // repeated string file_to_generate = 1;
+ int file_to_generate_size() const;
+ private:
+ int _internal_file_to_generate_size() const;
+ public:
+ void clear_file_to_generate();
+ const std::string& file_to_generate(int index) const;
+ std::string* mutable_file_to_generate(int index);
+ void set_file_to_generate(int index, const std::string& value);
+ void set_file_to_generate(int index, std::string&& value);
+ void set_file_to_generate(int index, const char* value);
+ void set_file_to_generate(int index, const char* value, size_t size);
+ std::string* add_file_to_generate();
+ void add_file_to_generate(const std::string& value);
+ void add_file_to_generate(std::string&& value);
+ void add_file_to_generate(const char* value);
+ void add_file_to_generate(const char* value, size_t size);
+ const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& file_to_generate() const;
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_file_to_generate();
+ private:
+ const std::string& _internal_file_to_generate(int index) const;
+ std::string* _internal_add_file_to_generate();
+ public:
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ int proto_file_size() const;
+ private:
+ int _internal_proto_file_size() const;
+ public:
+ void clear_proto_file();
+ ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_proto_file(int index);
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >*
+ mutable_proto_file();
+ private:
+ const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& _internal_proto_file(int index) const;
+ ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _internal_add_proto_file();
+ public:
+ const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& proto_file(int index) const;
+ ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_proto_file();
+ const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
+ proto_file() const;
+
+ // optional string parameter = 2;
+ bool has_parameter() const;
+ private:
+ bool _internal_has_parameter() const;
+ public:
+ void clear_parameter();
+ const std::string& parameter() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_parameter(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_parameter();
+ PROTOBUF_NODISCARD std::string* release_parameter();
+ void set_allocated_parameter(std::string* parameter);
+ private:
+ const std::string& _internal_parameter() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_parameter(const std::string& value);
+ std::string* _internal_mutable_parameter();
+ public:
+
+ // optional .google.protobuf.compiler.Version compiler_version = 3;
+ bool has_compiler_version() const;
+ private:
+ bool _internal_has_compiler_version() const;
+ public:
+ void clear_compiler_version();
+ const ::PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const;
+ PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version();
+ void set_allocated_compiler_version(::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
+ private:
+ const ::PROTOBUF_NAMESPACE_ID::compiler::Version& _internal_compiler_version() const;
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* _internal_mutable_compiler_version();
+ public:
+ void unsafe_arena_set_allocated_compiler_version(
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version);
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* unsafe_arena_release_compiler_version();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
+ private:
+ class _Internal;
+
+ template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> file_to_generate_;
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto > proto_file_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr parameter_;
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version_;
+ friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PROTOC_EXPORT CodeGeneratorResponse_File final :
+ public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ {
+ public:
+ inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {}
+ ~CodeGeneratorResponse_File() override;
+ explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
+ CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
+ : CodeGeneratorResponse_File() {
+ *this = ::std::move(from);
+ }
+
+ inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
+ CopyFrom(from);
+ return *this;
+ }
+ inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept {
+ if (this == &from) return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+ #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+ #endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ ) {
+ InternalSwap(&from);
+ } else {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+ }
+ inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+ }
+
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+ return GetDescriptor();
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+ return default_instance().GetMetadata().descriptor;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+ return default_instance().GetMetadata().reflection;
+ }
+ static const CodeGeneratorResponse_File& default_instance() {
+ return *internal_default_instance();
+ }
+ static inline const CodeGeneratorResponse_File* internal_default_instance() {
+ return reinterpret_cast<const CodeGeneratorResponse_File*>(
+ &_CodeGeneratorResponse_File_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages =
+ 2;
+
+ friend void swap(CodeGeneratorResponse_File& a, CodeGeneratorResponse_File& b) {
+ a.Swap(&b);
+ }
+ inline void Swap(CodeGeneratorResponse_File* other) {
+ if (other == this) return;
+ #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr &&
+ GetOwningArena() == other->GetOwningArena()) {
+ #else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena()) {
+ #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ } else {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorResponse_File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+ return CreateMaybeMessage<CodeGeneratorResponse_File>(arena);
+ }
+ using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+ void CopyFrom(const CodeGeneratorResponse_File& from);
+ using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+ void MergeFrom(const CodeGeneratorResponse_File& from);
+ private:
+ static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
+ public:
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final { return _cached_size_.Get(); }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const final;
+ void InternalSwap(CodeGeneratorResponse_File* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+ return "google.protobuf.compiler.CodeGeneratorResponse.File";
+ }
+ protected:
+ explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned = false);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+ public:
+
+ static const ClassData _class_data_;
+ const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+ ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ enum : int {
+ kNameFieldNumber = 1,
+ kInsertionPointFieldNumber = 2,
+ kContentFieldNumber = 15,
+ kGeneratedCodeInfoFieldNumber = 16,
+ };
+ // optional string name = 1;
+ bool has_name() const;
+ private:
+ bool _internal_has_name() const;
+ public:
+ void clear_name();
+ const std::string& name() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_name(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_name();
+ PROTOBUF_NODISCARD std::string* release_name();
+ void set_allocated_name(std::string* name);
+ private:
+ const std::string& _internal_name() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
+ std::string* _internal_mutable_name();
+ public:
+
+ // optional string insertion_point = 2;
+ bool has_insertion_point() const;
+ private:
+ bool _internal_has_insertion_point() const;
+ public:
+ void clear_insertion_point();
+ const std::string& insertion_point() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_insertion_point(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_insertion_point();
+ PROTOBUF_NODISCARD std::string* release_insertion_point();
+ void set_allocated_insertion_point(std::string* insertion_point);
+ private:
+ const std::string& _internal_insertion_point() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point(const std::string& value);
+ std::string* _internal_mutable_insertion_point();
+ public:
+
+ // optional string content = 15;
+ bool has_content() const;
+ private:
+ bool _internal_has_content() const;
+ public:
+ void clear_content();
+ const std::string& content() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_content(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_content();
+ PROTOBUF_NODISCARD std::string* release_content();
+ void set_allocated_content(std::string* content);
+ private:
+ const std::string& _internal_content() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_content(const std::string& value);
+ std::string* _internal_mutable_content();
+ public:
+
+ // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+ bool has_generated_code_info() const;
+ private:
+ bool _internal_has_generated_code_info() const;
+ public:
+ void clear_generated_code_info();
+ const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const;
+ PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info();
+ void set_allocated_generated_code_info(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
+ private:
+ const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& _internal_generated_code_info() const;
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _internal_mutable_generated_code_info();
+ public:
+ void unsafe_arena_set_allocated_generated_code_info(
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info);
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* unsafe_arena_release_generated_code_info();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
+ private:
+ class _Internal;
+
+ template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr insertion_point_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_;
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info_;
+ friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PROTOC_EXPORT CodeGeneratorResponse final :
+ public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ {
+ public:
+ inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {}
+ ~CodeGeneratorResponse() override;
+ explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
+
+ CodeGeneratorResponse(const CodeGeneratorResponse& from);
+ CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
+ : CodeGeneratorResponse() {
+ *this = ::std::move(from);
+ }
+
+ inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
+ CopyFrom(from);
+ return *this;
+ }
+ inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept {
+ if (this == &from) return *this;
+ if (GetOwningArena() == from.GetOwningArena()
+ #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
+ && GetOwningArena() != nullptr
+ #endif // !PROTOBUF_FORCE_COPY_IN_MOVE
+ ) {
+ InternalSwap(&from);
+ } else {
+ CopyFrom(from);
+ }
+ return *this;
+ }
+
+ inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance);
+ }
+ inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+ }
+
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+ return GetDescriptor();
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+ return default_instance().GetMetadata().descriptor;
+ }
+ static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+ return default_instance().GetMetadata().reflection;
+ }
+ static const CodeGeneratorResponse& default_instance() {
+ return *internal_default_instance();
+ }
+ static inline const CodeGeneratorResponse* internal_default_instance() {
+ return reinterpret_cast<const CodeGeneratorResponse*>(
+ &_CodeGeneratorResponse_default_instance_);
+ }
+ static constexpr int kIndexInFileMessages =
+ 3;
+
+ friend void swap(CodeGeneratorResponse& a, CodeGeneratorResponse& b) {
+ a.Swap(&b);
+ }
+ inline void Swap(CodeGeneratorResponse* other) {
+ if (other == this) return;
+ #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() != nullptr &&
+ GetOwningArena() == other->GetOwningArena()) {
+ #else // PROTOBUF_FORCE_COPY_IN_SWAP
+ if (GetOwningArena() == other->GetOwningArena()) {
+ #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
+ InternalSwap(other);
+ } else {
+ ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+ }
+ }
+ void UnsafeArenaSwap(CodeGeneratorResponse* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
+ InternalSwap(other);
+ }
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
+ return CreateMaybeMessage<CodeGeneratorResponse>(arena);
+ }
+ using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
+ void CopyFrom(const CodeGeneratorResponse& from);
+ using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
+ void MergeFrom(const CodeGeneratorResponse& from);
+ private:
+ static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from);
+ public:
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+ bool IsInitialized() const final;
+
+ size_t ByteSizeLong() const final;
+ const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+ uint8_t* _InternalSerialize(
+ uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+ int GetCachedSize() const final { return _cached_size_.Get(); }
+
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const final;
+ void InternalSwap(CodeGeneratorResponse* other);
+
+ private:
+ friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+ static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+ return "google.protobuf.compiler.CodeGeneratorResponse";
+ }
+ protected:
+ explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena,
+ bool is_message_owned = false);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+ public:
+
+ static const ClassData _class_data_;
+ const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;
+
+ ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+
+ // nested types ----------------------------------------------------
+
+ typedef CodeGeneratorResponse_File File;
+
+ typedef CodeGeneratorResponse_Feature Feature;
+ static constexpr Feature FEATURE_NONE =
+ CodeGeneratorResponse_Feature_FEATURE_NONE;
+ static constexpr Feature FEATURE_PROTO3_OPTIONAL =
+ CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL;
+ static inline bool Feature_IsValid(int value) {
+ return CodeGeneratorResponse_Feature_IsValid(value);
+ }
+ static constexpr Feature Feature_MIN =
+ CodeGeneratorResponse_Feature_Feature_MIN;
+ static constexpr Feature Feature_MAX =
+ CodeGeneratorResponse_Feature_Feature_MAX;
+ static constexpr int Feature_ARRAYSIZE =
+ CodeGeneratorResponse_Feature_Feature_ARRAYSIZE;
+ static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+ Feature_descriptor() {
+ return CodeGeneratorResponse_Feature_descriptor();
+ }
+ template<typename T>
+ static inline const std::string& Feature_Name(T enum_t_value) {
+ static_assert(::std::is_same<T, Feature>::value ||
+ ::std::is_integral<T>::value,
+ "Incorrect type passed to function Feature_Name.");
+ return CodeGeneratorResponse_Feature_Name(enum_t_value);
+ }
+ static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+ Feature* value) {
+ return CodeGeneratorResponse_Feature_Parse(name, value);
+ }
+
+ // accessors -------------------------------------------------------
+
+ enum : int {
+ kFileFieldNumber = 15,
+ kErrorFieldNumber = 1,
+ kSupportedFeaturesFieldNumber = 2,
+ };
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ int file_size() const;
+ private:
+ int _internal_file_size() const;
+ public:
+ void clear_file();
+ ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >*
+ mutable_file();
+ private:
+ const ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& _internal_file(int index) const;
+ ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* _internal_add_file();
+ public:
+ const ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& file(int index) const;
+ ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* add_file();
+ const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >&
+ file() const;
+
+ // optional string error = 1;
+ bool has_error() const;
+ private:
+ bool _internal_has_error() const;
+ public:
+ void clear_error();
+ const std::string& error() const;
+ template <typename ArgT0 = const std::string&, typename... ArgT>
+ void set_error(ArgT0&& arg0, ArgT... args);
+ std::string* mutable_error();
+ PROTOBUF_NODISCARD std::string* release_error();
+ void set_allocated_error(std::string* error);
+ private:
+ const std::string& _internal_error() const;
+ inline PROTOBUF_ALWAYS_INLINE void _internal_set_error(const std::string& value);
+ std::string* _internal_mutable_error();
+ public:
+
+ // optional uint64 supported_features = 2;
+ bool has_supported_features() const;
+ private:
+ bool _internal_has_supported_features() const;
+ public:
+ void clear_supported_features();
+ uint64_t supported_features() const;
+ void set_supported_features(uint64_t value);
+ private:
+ uint64_t _internal_supported_features() const;
+ void _internal_set_supported_features(uint64_t value);
+ public:
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
+ private:
+ class _Internal;
+
+ template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+ mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+ ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File > file_;
+ ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr error_;
+ uint64_t supported_features_;
+ friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif // __GNUC__
+// Version
+
+// optional int32 major = 1;
+inline bool Version::_internal_has_major() const {
+ bool value = (_has_bits_[0] & 0x00000002u) != 0;
+ return value;
+}
+inline bool Version::has_major() const {
+ return _internal_has_major();
+}
+inline void Version::clear_major() {
+ major_ = 0;
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline int32_t Version::_internal_major() const {
+ return major_;
+}
+inline int32_t Version::major() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major)
+ return _internal_major();
+}
+inline void Version::_internal_set_major(int32_t value) {
+ _has_bits_[0] |= 0x00000002u;
+ major_ = value;
+}
+inline void Version::set_major(int32_t value) {
+ _internal_set_major(value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major)
+}
+
+// optional int32 minor = 2;
+inline bool Version::_internal_has_minor() const {
+ bool value = (_has_bits_[0] & 0x00000004u) != 0;
+ return value;
+}
+inline bool Version::has_minor() const {
+ return _internal_has_minor();
+}
+inline void Version::clear_minor() {
+ minor_ = 0;
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline int32_t Version::_internal_minor() const {
+ return minor_;
+}
+inline int32_t Version::minor() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor)
+ return _internal_minor();
+}
+inline void Version::_internal_set_minor(int32_t value) {
+ _has_bits_[0] |= 0x00000004u;
+ minor_ = value;
+}
+inline void Version::set_minor(int32_t value) {
+ _internal_set_minor(value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor)
+}
+
+// optional int32 patch = 3;
+inline bool Version::_internal_has_patch() const {
+ bool value = (_has_bits_[0] & 0x00000008u) != 0;
+ return value;
+}
+inline bool Version::has_patch() const {
+ return _internal_has_patch();
+}
+inline void Version::clear_patch() {
+ patch_ = 0;
+ _has_bits_[0] &= ~0x00000008u;
+}
+inline int32_t Version::_internal_patch() const {
+ return patch_;
+}
+inline int32_t Version::patch() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch)
+ return _internal_patch();
+}
+inline void Version::_internal_set_patch(int32_t value) {
+ _has_bits_[0] |= 0x00000008u;
+ patch_ = value;
+}
+inline void Version::set_patch(int32_t value) {
+ _internal_set_patch(value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch)
+}
+
+// optional string suffix = 4;
+inline bool Version::_internal_has_suffix() const {
+ bool value = (_has_bits_[0] & 0x00000001u) != 0;
+ return value;
+}
+inline bool Version::has_suffix() const {
+ return _internal_has_suffix();
+}
+inline void Version::clear_suffix() {
+ suffix_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& Version::suffix() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix)
+ return _internal_suffix();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void Version::set_suffix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix)
+}
+inline std::string* Version::mutable_suffix() {
+ std::string* _s = _internal_mutable_suffix();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix)
+ return _s;
+}
+inline const std::string& Version::_internal_suffix() const {
+ return suffix_.Get();
+}
+inline void Version::_internal_set_suffix(const std::string& value) {
+ _has_bits_[0] |= 0x00000001u;
+ suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* Version::_internal_mutable_suffix() {
+ _has_bits_[0] |= 0x00000001u;
+ return suffix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* Version::release_suffix() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix)
+ if (!_internal_has_suffix()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000001u;
+ auto* p = suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (suffix_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void Version::set_allocated_suffix(std::string* suffix) {
+ if (suffix != nullptr) {
+ _has_bits_[0] |= 0x00000001u;
+ } else {
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ suffix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), suffix,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (suffix_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+inline int CodeGeneratorRequest::_internal_file_to_generate_size() const {
+ return file_to_generate_.size();
+}
+inline int CodeGeneratorRequest::file_to_generate_size() const {
+ return _internal_file_to_generate_size();
+}
+inline void CodeGeneratorRequest::clear_file_to_generate() {
+ file_to_generate_.Clear();
+}
+inline std::string* CodeGeneratorRequest::add_file_to_generate() {
+ std::string* _s = _internal_add_file_to_generate();
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return _s;
+}
+inline const std::string& CodeGeneratorRequest::_internal_file_to_generate(int index) const {
+ return file_to_generate_.Get(index);
+}
+inline const std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return _internal_file_to_generate(index);
+}
+inline std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_.Mutable(index);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const std::string& value) {
+ file_to_generate_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, std::string&& value) {
+ file_to_generate_.Mutable(index)->assign(std::move(value));
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+ GOOGLE_DCHECK(value != nullptr);
+ file_to_generate_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+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);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline std::string* CodeGeneratorRequest::_internal_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);
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::add_file_to_generate(std::string&& value) {
+ file_to_generate_.Add(std::move(value));
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+ GOOGLE_DCHECK(value != nullptr);
+ file_to_generate_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+ file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+inline bool CodeGeneratorRequest::_internal_has_parameter() const {
+ bool value = (_has_bits_[0] & 0x00000001u) != 0;
+ return value;
+}
+inline bool CodeGeneratorRequest::has_parameter() const {
+ return _internal_has_parameter();
+}
+inline void CodeGeneratorRequest::clear_parameter() {
+ parameter_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& CodeGeneratorRequest::parameter() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return _internal_parameter();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorRequest::set_parameter(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline std::string* CodeGeneratorRequest::mutable_parameter() {
+ std::string* _s = _internal_mutable_parameter();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return _s;
+}
+inline const std::string& CodeGeneratorRequest::_internal_parameter() const {
+ return parameter_.Get();
+}
+inline void CodeGeneratorRequest::_internal_set_parameter(const std::string& value) {
+ _has_bits_[0] |= 0x00000001u;
+ parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorRequest::_internal_mutable_parameter() {
+ _has_bits_[0] |= 0x00000001u;
+ return parameter_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorRequest::release_parameter() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ if (!_internal_has_parameter()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000001u;
+ auto* p = parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (parameter_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void CodeGeneratorRequest::set_allocated_parameter(std::string* parameter) {
+ if (parameter != nullptr) {
+ _has_bits_[0] |= 0x00000001u;
+ } else {
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ parameter_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), parameter,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (parameter_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+inline int CodeGeneratorRequest::_internal_proto_file_size() const {
+ return proto_file_.size();
+}
+inline int CodeGeneratorRequest::proto_file_size() const {
+ return _internal_proto_file_size();
+}
+inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Mutable(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return &proto_file_;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::_internal_proto_file(int index) const {
+ return proto_file_.Get(index);
+}
+inline const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return _internal_proto_file(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::_internal_add_proto_file() {
+ return proto_file_.Add();
+}
+inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+ ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _add = _internal_add_proto_file();
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return _add;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
+
+// optional .google.protobuf.compiler.Version compiler_version = 3;
+inline bool CodeGeneratorRequest::_internal_has_compiler_version() const {
+ bool value = (_has_bits_[0] & 0x00000002u) != 0;
+ PROTOBUF_ASSUME(!value || compiler_version_ != nullptr);
+ return value;
+}
+inline bool CodeGeneratorRequest::has_compiler_version() const {
+ return _internal_has_compiler_version();
+}
+inline void CodeGeneratorRequest::clear_compiler_version() {
+ if (compiler_version_ != nullptr) compiler_version_->Clear();
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const {
+ const ::PROTOBUF_NAMESPACE_ID::compiler::Version* p = compiler_version_;
+ return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::compiler::Version&>(
+ ::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_);
+}
+inline const ::PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+ return _internal_compiler_version();
+}
+inline void CodeGeneratorRequest::unsafe_arena_set_allocated_compiler_version(
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) {
+ if (GetArenaForAllocation() == nullptr) {
+ delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(compiler_version_);
+ }
+ compiler_version_ = compiler_version;
+ if (compiler_version) {
+ _has_bits_[0] |= 0x00000002u;
+ } else {
+ _has_bits_[0] &= ~0x00000002u;
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::release_compiler_version() {
+ _has_bits_[0] &= ~0x00000002u;
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* temp = compiler_version_;
+ compiler_version_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+ auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+ temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+ if (GetArenaForAllocation() == nullptr) { delete old; }
+#else // PROTOBUF_FORCE_COPY_IN_RELEASE
+ if (GetArenaForAllocation() != nullptr) {
+ temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+ }
+#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE
+ return temp;
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::unsafe_arena_release_compiler_version() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+ _has_bits_[0] &= ~0x00000002u;
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* temp = compiler_version_;
+ compiler_version_ = nullptr;
+ return temp;
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::_internal_mutable_compiler_version() {
+ _has_bits_[0] |= 0x00000002u;
+ if (compiler_version_ == nullptr) {
+ auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(GetArenaForAllocation());
+ compiler_version_ = p;
+ }
+ return compiler_version_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
+ ::PROTOBUF_NAMESPACE_ID::compiler::Version* _msg = _internal_mutable_compiler_version();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+ return _msg;
+}
+inline void CodeGeneratorRequest::set_allocated_compiler_version(::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) {
+ ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
+ if (message_arena == nullptr) {
+ delete compiler_version_;
+ }
+ if (compiler_version) {
+ ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+ ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<::PROTOBUF_NAMESPACE_ID::compiler::Version>::GetOwningArena(compiler_version);
+ if (message_arena != submessage_arena) {
+ compiler_version = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+ message_arena, compiler_version, submessage_arena);
+ }
+ _has_bits_[0] |= 0x00000002u;
+ } else {
+ _has_bits_[0] &= ~0x00000002u;
+ }
+ compiler_version_ = compiler_version;
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+inline bool CodeGeneratorResponse_File::_internal_has_name() const {
+ bool value = (_has_bits_[0] & 0x00000001u) != 0;
+ return value;
+}
+inline bool CodeGeneratorResponse_File::has_name() const {
+ return _internal_has_name();
+}
+inline void CodeGeneratorResponse_File::clear_name() {
+ name_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& CodeGeneratorResponse_File::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return _internal_name();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline std::string* CodeGeneratorResponse_File::mutable_name() {
+ std::string* _s = _internal_mutable_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return _s;
+}
+inline const std::string& CodeGeneratorResponse_File::_internal_name() const {
+ return name_.Get();
+}
+inline void CodeGeneratorResponse_File::_internal_set_name(const std::string& value) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::_internal_mutable_name() {
+ _has_bits_[0] |= 0x00000001u;
+ return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ if (!_internal_has_name()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000001u;
+ auto* p = name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void CodeGeneratorResponse_File::set_allocated_name(std::string* name) {
+ if (name != nullptr) {
+ _has_bits_[0] |= 0x00000001u;
+ } else {
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const {
+ bool value = (_has_bits_[0] & 0x00000002u) != 0;
+ return value;
+}
+inline bool CodeGeneratorResponse_File::has_insertion_point() const {
+ return _internal_has_insertion_point();
+}
+inline void CodeGeneratorResponse_File::clear_insertion_point() {
+ insertion_point_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline const std::string& CodeGeneratorResponse_File::insertion_point() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return _internal_insertion_point();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_insertion_point(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+ std::string* _s = _internal_mutable_insertion_point();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return _s;
+}
+inline const std::string& CodeGeneratorResponse_File::_internal_insertion_point() const {
+ return insertion_point_.Get();
+}
+inline void CodeGeneratorResponse_File::_internal_set_insertion_point(const std::string& value) {
+ _has_bits_[0] |= 0x00000002u;
+ insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::_internal_mutable_insertion_point() {
+ _has_bits_[0] |= 0x00000002u;
+ return insertion_point_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::release_insertion_point() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ if (!_internal_has_insertion_point()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000002u;
+ auto* p = insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (insertion_point_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::string* insertion_point) {
+ if (insertion_point != nullptr) {
+ _has_bits_[0] |= 0x00000002u;
+ } else {
+ _has_bits_[0] &= ~0x00000002u;
+ }
+ insertion_point_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), insertion_point,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (insertion_point_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+inline bool CodeGeneratorResponse_File::_internal_has_content() const {
+ bool value = (_has_bits_[0] & 0x00000004u) != 0;
+ return value;
+}
+inline bool CodeGeneratorResponse_File::has_content() const {
+ return _internal_has_content();
+}
+inline void CodeGeneratorResponse_File::clear_content() {
+ content_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline const std::string& CodeGeneratorResponse_File::content() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return _internal_content();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse_File::set_content(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline std::string* CodeGeneratorResponse_File::mutable_content() {
+ std::string* _s = _internal_mutable_content();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return _s;
+}
+inline const std::string& CodeGeneratorResponse_File::_internal_content() const {
+ return content_.Get();
+}
+inline void CodeGeneratorResponse_File::_internal_set_content(const std::string& value) {
+ _has_bits_[0] |= 0x00000004u;
+ content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::_internal_mutable_content() {
+ _has_bits_[0] |= 0x00000004u;
+ return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse_File::release_content() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ if (!_internal_has_content()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000004u;
+ auto* p = content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (content_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void CodeGeneratorResponse_File::set_allocated_content(std::string* content) {
+ if (content != nullptr) {
+ _has_bits_[0] |= 0x00000004u;
+ } else {
+ _has_bits_[0] &= ~0x00000004u;
+ }
+ content_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), content,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (content_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
+inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const {
+ bool value = (_has_bits_[0] & 0x00000008u) != 0;
+ PROTOBUF_ASSUME(!value || generated_code_info_ != nullptr);
+ return value;
+}
+inline bool CodeGeneratorResponse_File::has_generated_code_info() const {
+ return _internal_has_generated_code_info();
+}
+inline const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::_internal_generated_code_info() const {
+ const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* p = generated_code_info_;
+ return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&>(
+ ::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_);
+}
+inline const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::generated_code_info() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+ return _internal_generated_code_info();
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_generated_code_info(
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) {
+ if (GetArenaForAllocation() == nullptr) {
+ delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_);
+ }
+ generated_code_info_ = generated_code_info;
+ if (generated_code_info) {
+ _has_bits_[0] |= 0x00000008u;
+ } else {
+ _has_bits_[0] &= ~0x00000008u;
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::release_generated_code_info() {
+ _has_bits_[0] &= ~0x00000008u;
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_;
+ generated_code_info_ = nullptr;
+#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
+ auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
+ temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+ if (GetArenaForAllocation() == nullptr) { delete old; }
+#else // PROTOBUF_FORCE_COPY_IN_RELEASE
+ if (GetArenaForAllocation() != nullptr) {
+ temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+ }
+#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE
+ return temp;
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::unsafe_arena_release_generated_code_info() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+ _has_bits_[0] &= ~0x00000008u;
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_;
+ generated_code_info_ = nullptr;
+ return temp;
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::_internal_mutable_generated_code_info() {
+ _has_bits_[0] |= 0x00000008u;
+ if (generated_code_info_ == nullptr) {
+ auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo>(GetArenaForAllocation());
+ generated_code_info_ = p;
+ }
+ return generated_code_info_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::mutable_generated_code_info() {
+ ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _msg = _internal_mutable_generated_code_info();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+ return _msg;
+}
+inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) {
+ ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
+ if (message_arena == nullptr) {
+ delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_);
+ }
+ if (generated_code_info) {
+ ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+ ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<
+ ::PROTOBUF_NAMESPACE_ID::MessageLite>::GetOwningArena(
+ reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info));
+ if (message_arena != submessage_arena) {
+ generated_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+ message_arena, generated_code_info, submessage_arena);
+ }
+ _has_bits_[0] |= 0x00000008u;
+ } else {
+ _has_bits_[0] &= ~0x00000008u;
+ }
+ generated_code_info_ = generated_code_info;
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+inline bool CodeGeneratorResponse::_internal_has_error() const {
+ bool value = (_has_bits_[0] & 0x00000001u) != 0;
+ return value;
+}
+inline bool CodeGeneratorResponse::has_error() const {
+ return _internal_has_error();
+}
+inline void CodeGeneratorResponse::clear_error() {
+ error_.ClearToEmpty();
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& CodeGeneratorResponse::error() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return _internal_error();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void CodeGeneratorResponse::set_error(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline std::string* CodeGeneratorResponse::mutable_error() {
+ std::string* _s = _internal_mutable_error();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return _s;
+}
+inline const std::string& CodeGeneratorResponse::_internal_error() const {
+ return error_.Get();
+}
+inline void CodeGeneratorResponse::_internal_set_error(const std::string& value) {
+ _has_bits_[0] |= 0x00000001u;
+ error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse::_internal_mutable_error() {
+ _has_bits_[0] |= 0x00000001u;
+ return error_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation());
+}
+inline std::string* CodeGeneratorResponse::release_error() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
+ if (!_internal_has_error()) {
+ return nullptr;
+ }
+ _has_bits_[0] &= ~0x00000001u;
+ auto* p = error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (error_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ return p;
+}
+inline void CodeGeneratorResponse::set_allocated_error(std::string* error) {
+ if (error != nullptr) {
+ _has_bits_[0] |= 0x00000001u;
+ } else {
+ _has_bits_[0] &= ~0x00000001u;
+ }
+ error_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), error,
+ GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ if (error_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) {
+ error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation());
+ }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// optional uint64 supported_features = 2;
+inline bool CodeGeneratorResponse::_internal_has_supported_features() const {
+ bool value = (_has_bits_[0] & 0x00000002u) != 0;
+ return value;
+}
+inline bool CodeGeneratorResponse::has_supported_features() const {
+ return _internal_has_supported_features();
+}
+inline void CodeGeneratorResponse::clear_supported_features() {
+ supported_features_ = uint64_t{0u};
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline uint64_t CodeGeneratorResponse::_internal_supported_features() const {
+ return supported_features_;
+}
+inline uint64_t CodeGeneratorResponse::supported_features() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.supported_features)
+ return _internal_supported_features();
+}
+inline void CodeGeneratorResponse::_internal_set_supported_features(uint64_t value) {
+ _has_bits_[0] |= 0x00000002u;
+ supported_features_ = value;
+}
+inline void CodeGeneratorResponse::set_supported_features(uint64_t value) {
+ _internal_set_supported_features(value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.supported_features)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+inline int CodeGeneratorResponse::_internal_file_size() const {
+ return file_.size();
+}
+inline int CodeGeneratorResponse::file_size() const {
+ return _internal_file_size();
+}
+inline void CodeGeneratorResponse::clear_file() {
+ file_.Clear();
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Mutable(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return &file_;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::_internal_file(int index) const {
+ return file_.Get(index);
+}
+inline const ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return _internal_file(index);
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::_internal_add_file() {
+ return file_.Add();
+}
+inline ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+ ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* _add = _internal_add_file();
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return _add;
+}
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic pop
+#endif // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace compiler
+PROTOBUF_NAMESPACE_CLOSE
+
+PROTOBUF_NAMESPACE_OPEN
+
+template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() {
+ return ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature_descriptor();
+}
+
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+
+#include <port_undef.inc>
+#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/plugin.proto b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.proto
new file mode 100644
index 00000000..9242aacc
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/plugin.proto
@@ -0,0 +1,183 @@
+// 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)
+//
+// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to
+// change.
+//
+// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
+// just a program that reads a CodeGeneratorRequest from stdin and writes a
+// CodeGeneratorResponse to stdout.
+//
+// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
+// of dealing with the raw protocol defined here.
+//
+// A plugin executable needs only to be placed somewhere in the path. The
+// plugin should be named "protoc-gen-$NAME", and will then be used when the
+// flag "--${NAME}_out" is passed to protoc.
+
+syntax = "proto2";
+
+package google.protobuf.compiler;
+option java_package = "com.google.protobuf.compiler";
+option java_outer_classname = "PluginProtos";
+
+option go_package = "google.golang.org/protobuf/types/pluginpb";
+
+import "google/protobuf/descriptor.proto";
+
+// The version number of protocol compiler.
+message Version {
+ optional int32 major = 1;
+ optional int32 minor = 2;
+ optional int32 patch = 3;
+ // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
+ // be empty for mainline stable releases.
+ optional string suffix = 4;
+}
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+message CodeGeneratorRequest {
+ // The .proto files that were explicitly listed on the command-line. The
+ // code generator should generate code only for these files. Each file's
+ // descriptor will be included in proto_file, below.
+ repeated string file_to_generate = 1;
+
+ // The generator parameter passed on the command-line.
+ optional string parameter = 2;
+
+ // FileDescriptorProtos for all files in files_to_generate and everything
+ // they import. The files will appear in topological order, so each file
+ // appears before any file that imports it.
+ //
+ // protoc guarantees that all proto_files will be written after
+ // the fields above, even though this is not technically guaranteed by the
+ // protobuf wire format. This theoretically could allow a plugin to stream
+ // in the FileDescriptorProtos and handle them one by one rather than read
+ // the entire set into memory at once. However, as of this writing, this
+ // is not similarly optimized on protoc's end -- it will store all fields in
+ // memory at once before sending them to the plugin.
+ //
+ // Type names of fields and extensions in the FileDescriptorProto are always
+ // fully qualified.
+ repeated FileDescriptorProto proto_file = 15;
+
+ // The version number of protocol compiler.
+ optional Version compiler_version = 3;
+
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+message CodeGeneratorResponse {
+ // Error message. If non-empty, code generation failed. The plugin process
+ // should exit with status code zero even if it reports an error in this way.
+ //
+ // This should be used to indicate errors in .proto files which prevent the
+ // code generator from generating correct code. Errors which indicate a
+ // problem in protoc itself -- such as the input CodeGeneratorRequest being
+ // unparseable -- should be reported by writing a message to stderr and
+ // exiting with a non-zero status code.
+ optional string error = 1;
+
+ // A bitmask of supported features that the code generator supports.
+ // This is a bitwise "or" of values from the Feature enum.
+ optional uint64 supported_features = 2;
+
+ // Sync with code_generator.h.
+ enum Feature {
+ FEATURE_NONE = 0;
+ FEATURE_PROTO3_OPTIONAL = 1;
+ }
+
+ // Represents a single generated file.
+ message File {
+ // The file name, relative to the output directory. The name must not
+ // contain "." or ".." components and must be relative, not be absolute (so,
+ // the file cannot lie outside the output directory). "/" must be used as
+ // the path separator, not "\".
+ //
+ // If the name is omitted, the content will be appended to the previous
+ // file. This allows the generator to break large files into small chunks,
+ // and allows the generated text to be streamed back to protoc so that large
+ // files need not reside completely in memory at one time. Note that as of
+ // this writing protoc does not optimize for this -- it will read the entire
+ // CodeGeneratorResponse before writing files to disk.
+ optional string name = 1;
+
+ // If non-empty, indicates that the named file should already exist, and the
+ // content here is to be inserted into that file at a defined insertion
+ // point. This feature allows a code generator to extend the output
+ // produced by another code generator. The original generator may provide
+ // insertion points by placing special annotations in the file that look
+ // like:
+ // @@protoc_insertion_point(NAME)
+ // The annotation can have arbitrary text before and after it on the line,
+ // which allows it to be placed in a comment. NAME should be replaced with
+ // an identifier naming the point -- this is what other generators will use
+ // as the insertion_point. Code inserted at this point will be placed
+ // immediately above the line containing the insertion point (thus multiple
+ // insertions to the same point will come out in the order they were added).
+ // The double-@ is intended to make it unlikely that the generated code
+ // could contain things that look like insertion points by accident.
+ //
+ // For example, the C++ code generator places the following line in the
+ // .pb.h files that it generates:
+ // // @@protoc_insertion_point(namespace_scope)
+ // This line appears within the scope of the file's package namespace, but
+ // outside of any particular class. Another plugin can then specify the
+ // insertion_point "namespace_scope" to generate additional classes or
+ // other declarations that should be placed in this scope.
+ //
+ // Note that if the line containing the insertion point begins with
+ // whitespace, the same whitespace will be added to every line of the
+ // inserted text. This is useful for languages like Python, where
+ // indentation matters. In these languages, the insertion point comment
+ // should be indented the same amount as any inserted code will need to be
+ // in order to work correctly in that context.
+ //
+ // The code generator that generates the initial file and the one which
+ // inserts into it must both run as part of a single invocation of protoc.
+ // Code generators are executed in the order in which they appear on the
+ // command line.
+ //
+ // If |insertion_point| is present, |name| must also be present.
+ optional string insertion_point = 2;
+
+ // The file contents.
+ optional string content = 15;
+
+ // Information describing the file content being inserted. If an insertion
+ // point is used, this information will be appropriately offset and inserted
+ // into the code generation metadata for the generated files.
+ optional GeneratedCodeInfo generated_code_info = 16;
+ }
+ repeated File file = 15;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.cc
new file mode 100644
index 00000000..96b52990
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.cc
@@ -0,0 +1,1577 @@
+// 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: robinson@google.com (Will Robinson)
+//
+// This module outputs pure-Python protocol message classes that will
+// largely be constructed at runtime via the metaclass in reflection.py.
+// In other words, our job is basically to output a Python equivalent
+// of the C++ *Descriptor objects, and fix up all circular references
+// within these objects.
+//
+// Note that the runtime performance of protocol message classes created in
+// this way is expected to be lousy. The plan is to create an alternate
+// generator that outputs a Python/C extension module that lets
+// performance-minded Python code leverage the fast C++ implementation
+// directly.
+
+#include <compiler/python/python_generator.h>
+
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <stubs/stringprintf.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <descriptor.h>
+#include <stubs/strutil.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+
+namespace {
+
+
+// Returns the Python module name expected for a given .proto filename.
+std::string ModuleName(const std::string& filename) {
+ std::string basename = StripProto(filename);
+ ReplaceCharacters(&basename, "-", '_');
+ ReplaceCharacters(&basename, "/", '.');
+ return basename + "_pb2";
+}
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing. See testPackageInitializationImport in
+// net/proto2/python/internal/reflection_test.py
+// to see why we need the alias.
+std::string ModuleAlias(const std::string& filename) {
+ std::string module_name = ModuleName(filename);
+ // We can't have dots in the module name, so we replace each with _dot_.
+ // But that could lead to a collision between a.b and a_dot_b, so we also
+ // duplicate each underscore.
+ GlobalReplaceSubstring("_", "__", &module_name);
+ GlobalReplaceSubstring(".", "_dot_", &module_name);
+ return module_name;
+}
+
+// Keywords reserved by the Python language.
+const char* const kKeywords[] = {
+ "False", "None", "True", "and", "as", "assert",
+ "async", "await", "break", "class", "continue", "def",
+ "del", "elif", "else", "except", "finally", "for",
+ "from", "global", "if", "import", "in", "is",
+ "lambda", "nonlocal", "not", "or", "pass", "raise",
+ "return", "try", "while", "with", "yield", "print",
+};
+const char* const* kKeywordsEnd =
+ kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
+
+bool ContainsPythonKeyword(const std::string& module_name) {
+ std::vector<std::string> tokens = Split(module_name, ".");
+ for (int i = 0; i < tokens.size(); ++i) {
+ if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool IsPythonKeyword(const std::string& name) {
+ return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd);
+}
+
+std::string ResolveKeyword(const std::string& name) {
+ if (IsPythonKeyword(name)) {
+ return "globals()['" + name + "']";
+ }
+ return name;
+}
+
+// Returns the name of all containing types for descriptor,
+// in order from outermost to innermost, followed by descriptor's
+// own name. Each name is separated by |separator|.
+template <typename DescriptorT>
+std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
+ const std::string& separator) {
+ std::string name = descriptor.name();
+ const Descriptor* parent = descriptor.containing_type();
+ if (parent != nullptr) {
+ std::string prefix = NamePrefixedWithNestedTypes(*parent, separator);
+ if (separator == "." && IsPythonKeyword(name)) {
+ return "getattr(" + prefix + ", '" + name + "')";
+ } else {
+ return prefix + separator + name;
+ }
+ }
+ if (separator == ".") {
+ name = ResolveKeyword(name);
+ }
+ return name;
+}
+
+// Name of the class attribute where we store the Python
+// descriptor.Descriptor instance for the generated class.
+// Must stay consistent with the _DESCRIPTOR_KEY constant
+// in proto2/public/reflection.py.
+const char kDescriptorKey[] = "DESCRIPTOR";
+
+// Does the file have top-level enums?
+inline bool HasTopLevelEnums(const FileDescriptor* file) {
+ return file->enum_type_count() > 0;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor* file) {
+ return file->service_count() > 0 && file->options().py_generic_services();
+}
+
+// Prints the common boilerplate needed at the top of every .py
+// file output by this generator.
+void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file,
+ bool descriptor_proto) {
+ // TODO(robinson): Allow parameterization of Python version?
+ printer->Print(
+ "# -*- coding: utf-8 -*-\n"
+ "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "# source: $filename$\n"
+ "\"\"\"Generated protocol buffer code.\"\"\"\n",
+ "filename", file->name());
+ if (HasTopLevelEnums(file)) {
+ printer->Print(
+ "from google.protobuf.internal import enum_type_wrapper\n");
+ }
+ printer->Print(
+ "from google.protobuf import descriptor as _descriptor\n"
+ "from google.protobuf import descriptor_pool as "
+ "_descriptor_pool\n"
+ "from google.protobuf import message as _message\n"
+ "from google.protobuf import reflection as _reflection\n"
+ "from google.protobuf import symbol_database as "
+ "_symbol_database\n");
+ if (HasGenericServices(file)) {
+ printer->Print(
+ "from google.protobuf import service as _service\n"
+ "from google.protobuf import service_reflection\n");
+ }
+
+ printer->Print(
+ "# @@protoc_insertion_point(imports)\n\n"
+ "_sym_db = _symbol_database.Default()\n");
+ printer->Print("\n\n");
+}
+
+// Returns a Python literal giving the default value for a field.
+// If the field specifies no explicit default value, we'll return
+// the default default value for the field type (zero for numbers,
+// empty string for strings, empty list for repeated fields, and
+// None for non-repeated, composite fields).
+//
+// TODO(robinson): Unify with code from
+// //compiler/cpp/internal/primitive_field.cc
+// //compiler/cpp/internal/enum_field.cc
+// //compiler/cpp/internal/string_field.cc
+std::string StringifyDefaultValue(const FieldDescriptor& field) {
+ if (field.is_repeated()) {
+ return "[]";
+ }
+
+ switch (field.cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return StrCat(field.default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return StrCat(field.default_value_uint32());
+ case FieldDescriptor::CPPTYPE_INT64:
+ return StrCat(field.default_value_int64());
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return StrCat(field.default_value_uint64());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field.default_value_double();
+ if (value == std::numeric_limits<double>::infinity()) {
+ // Python pre-2.6 on Windows does not parse "inf" correctly. However,
+ // a numeric literal that is too big for a double will become infinity.
+ return "1e10000";
+ } else if (value == -std::numeric_limits<double>::infinity()) {
+ // See above.
+ return "-1e10000";
+ } else if (value != value) {
+ // infinity * 0 = nan
+ return "(1e10000 * 0)";
+ } else {
+ return "float(" + SimpleDtoa(value) + ")";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field.default_value_float();
+ if (value == std::numeric_limits<float>::infinity()) {
+ // Python pre-2.6 on Windows does not parse "inf" correctly. However,
+ // a numeric literal that is too big for a double will become infinity.
+ return "1e10000";
+ } else if (value == -std::numeric_limits<float>::infinity()) {
+ // See above.
+ return "-1e10000";
+ } else if (value != value) {
+ // infinity - infinity = nan
+ return "(1e10000 * 0)";
+ } else {
+ return "float(" + SimpleFtoa(value) + ")";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field.default_value_bool() ? "True" : "False";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return StrCat(field.default_value_enum()->number());
+ case FieldDescriptor::CPPTYPE_STRING:
+ return "b\"" + CEscape(field.default_value_string()) +
+ (field.type() != FieldDescriptor::TYPE_STRING
+ ? "\""
+ : "\".decode('utf-8')");
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "None";
+ }
+ // (We could add a default case above but then we wouldn't get the nice
+ // compiler warning when a new type is added.)
+ GOOGLE_LOG(FATAL) << "Not reached.";
+ return "";
+}
+
+std::string StringifySyntax(FileDescriptor::Syntax syntax) {
+ switch (syntax) {
+ case FileDescriptor::SYNTAX_PROTO2:
+ return "proto2";
+ case FileDescriptor::SYNTAX_PROTO3:
+ return "proto3";
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ default:
+ GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
+ "and proto3 syntax.";
+ return "";
+ }
+}
+
+} // namespace
+
+Generator::Generator() : file_(nullptr) {}
+
+Generator::~Generator() {}
+
+uint64_t Generator::GetSupportedFeatures() const {
+ return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
+}
+
+bool Generator::Generate(const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* context, std::string* error) const {
+ // -----------------------------------------------------------------
+ // parse generator options
+ bool cpp_generated_lib_linked = false;
+
+ std::vector<std::pair<std::string, std::string> > options;
+ ParseGeneratorParameter(parameter, &options);
+
+ for (int i = 0; i < options.size(); i++) {
+ if (options[i].first == "cpp_generated_lib_linked") {
+ cpp_generated_lib_linked = true;
+ } else {
+ *error = "Unknown generator option: " + options[i].first;
+ return false;
+ }
+ }
+
+ // Completely serialize all Generate() calls on this instance. The
+ // thread-safety constraints of the CodeGenerator interface aren't clear so
+ // just be as conservative as possible. It's easier to relax this later if
+ // we need to, but I doubt it will be an issue.
+ // TODO(kenton): The proper thing to do would be to allocate any state on
+ // the stack and use that, so that the Generator class itself does not need
+ // to have any mutable members. Then it is implicitly thread-safe.
+ MutexLock lock(&mutex_);
+ file_ = file;
+ std::string module_name = ModuleName(file->name());
+ std::string filename = module_name;
+ ReplaceCharacters(&filename, ".", '/');
+ filename += ".py";
+
+ pure_python_workable_ = !cpp_generated_lib_linked;
+ if (HasPrefixString(file->name(), "google/protobuf/")) {
+ pure_python_workable_ = true;
+ }
+
+ FileDescriptorProto fdp;
+ file_->CopyTo(&fdp);
+ fdp.SerializeToString(&file_descriptor_serialized_);
+
+
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ io::Printer printer(output.get(), '$');
+ printer_ = &printer;
+
+ PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+ if (pure_python_workable_) {
+ PrintImports();
+ }
+ PrintFileDescriptor();
+ PrintTopLevelEnums();
+ PrintTopLevelExtensions();
+ if (pure_python_workable_) {
+ if (GeneratingDescriptorProto()) {
+ printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
+ printer_->Indent();
+ // Create enums before message descriptors
+ PrintAllNestedEnumsInFile(StripPrintDescriptor::kCreate);
+ PrintMessageDescriptors(StripPrintDescriptor::kCreate);
+ FixForeignFieldsInDescriptors();
+ printer_->Outdent();
+ printer_->Print("else:\n");
+ printer_->Indent();
+ }
+ // Find the message descriptors first and then use the message
+ // descriptor to find enums.
+ PrintMessageDescriptors(StripPrintDescriptor::kFind);
+ PrintAllNestedEnumsInFile(StripPrintDescriptor::kFind);
+ if (GeneratingDescriptorProto()) {
+ printer_->Outdent();
+ }
+ }
+ PrintMessages();
+ if (pure_python_workable_) {
+ PrintServiceDescriptors();
+
+ printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
+ printer_->Indent();
+
+ // We have to fix up the extensions after the message classes themselves,
+ // since they need to call static RegisterExtension() methods on these
+ // classes.
+ FixForeignFieldsInExtensions();
+ // Descriptor options may have custom extensions. These custom options
+ // can only be successfully parsed after we register corresponding
+ // extensions. Therefore we parse all options again here to recognize
+ // custom options that may be unknown when we define the descriptors.
+ // This does not apply to services because they are not used by extensions.
+ FixAllDescriptorOptions();
+
+ // Set serialized_start and serialized_end.
+ SetSerializedPbInterval();
+
+ printer_->Outdent();
+ }
+ if (HasGenericServices(file)) {
+ PrintServices();
+ }
+
+ printer.Print("# @@protoc_insertion_point(module_scope)\n");
+
+ return !printer.failed();
+}
+
+
+// Prints Python imports for all modules imported by |file|.
+void Generator::PrintImports() const {
+ for (int i = 0; i < file_->dependency_count(); ++i) {
+ const std::string& filename = file_->dependency(i)->name();
+
+ std::string module_name = ModuleName(filename);
+ std::string module_alias = ModuleAlias(filename);
+ if (ContainsPythonKeyword(module_name)) {
+ // If the module path contains a Python keyword, we have to quote the
+ // module name and import it using importlib. Otherwise the usual kind of
+ // import statement would result in a syntax error from the presence of
+ // the keyword.
+ printer_->Print("import importlib\n");
+ printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias",
+ module_alias, "name", module_name);
+ } else {
+ int last_dot_pos = module_name.rfind('.');
+ std::string import_statement;
+ if (last_dot_pos == std::string::npos) {
+ // NOTE(petya): this is not tested as it would require a protocol buffer
+ // outside of any package, and I don't think that is easily achievable.
+ import_statement = "import " + module_name;
+ } else {
+ import_statement = "from " + module_name.substr(0, last_dot_pos) +
+ " import " + module_name.substr(last_dot_pos + 1);
+ }
+ printer_->Print("$statement$ as $alias$\n", "statement", import_statement,
+ "alias", module_alias);
+ }
+
+ CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
+ }
+ printer_->Print("\n");
+
+ // Print public imports.
+ for (int i = 0; i < file_->public_dependency_count(); ++i) {
+ std::string module_name = ModuleName(file_->public_dependency(i)->name());
+ printer_->Print("from $module$ import *\n", "module", module_name);
+ }
+ printer_->Print("\n");
+}
+
+// Prints the single file descriptor for this file.
+void Generator::PrintFileDescriptor() const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["name"] = file_->name();
+ m["package"] = file_->package();
+ m["syntax"] = StringifySyntax(file_->syntax());
+ m["options"] = OptionsValue(file_->options().SerializeAsString());
+ m["serialized_descriptor"] = strings::CHexEscape(file_descriptor_serialized_);
+ if (GeneratingDescriptorProto()) {
+ printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
+ printer_->Indent();
+ // Pure python's AddSerializedFile() depend on the generated
+ // descriptor_pb2.py thus we can not use AddSerializedFile() when
+ // generated descriptor.proto for pure python.
+ const char file_descriptor_template[] =
+ "$descriptor_name$ = _descriptor.FileDescriptor(\n"
+ " name='$name$',\n"
+ " package='$package$',\n"
+ " syntax='$syntax$',\n"
+ " serialized_options=$options$,\n"
+ " create_key=_descriptor._internal_create_key,\n";
+ printer_->Print(m, file_descriptor_template);
+ printer_->Indent();
+ if (pure_python_workable_) {
+ printer_->Print("serialized_pb=b'$value$'\n", "value",
+ strings::CHexEscape(file_descriptor_serialized_));
+ if (file_->dependency_count() != 0) {
+ printer_->Print(",\ndependencies=[");
+ for (int i = 0; i < file_->dependency_count(); ++i) {
+ std::string module_alias = ModuleAlias(file_->dependency(i)->name());
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+ module_alias);
+ }
+ printer_->Print("]");
+ }
+ if (file_->public_dependency_count() > 0) {
+ printer_->Print(",\npublic_dependencies=[");
+ for (int i = 0; i < file_->public_dependency_count(); ++i) {
+ std::string module_alias =
+ ModuleAlias(file_->public_dependency(i)->name());
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+ module_alias);
+ }
+ printer_->Print("]");
+ }
+ } else {
+ printer_->Print("serialized_pb=''\n");
+ }
+
+ // TODO(falk): Also print options and fix the message_type, enum_type,
+ // service and extension later in the generation.
+
+ printer_->Outdent();
+ printer_->Print(")\n");
+
+ printer_->Outdent();
+ printer_->Print("else:\n");
+ printer_->Indent();
+ }
+ printer_->Print(m,
+ "$descriptor_name$ = "
+ "_descriptor_pool.Default().AddSerializedFile(b'$serialized_"
+ "descriptor$')\n");
+ if (GeneratingDescriptorProto()) {
+ printer_->Outdent();
+ }
+ printer_->Print("\n");
+}
+
+// Prints descriptors and module-level constants for all top-level
+// enums defined in |file|.
+void Generator::PrintTopLevelEnums() const {
+ std::vector<std::pair<std::string, int> > top_level_enum_values;
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+ PrintFindEnum(enum_descriptor);
+ printer_->Print(
+ "$name$ = "
+ "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
+ "name", ResolveKeyword(enum_descriptor.name()), "descriptor_name",
+ ModuleLevelDescriptorName(enum_descriptor));
+ printer_->Print("\n");
+
+ for (int j = 0; j < enum_descriptor.value_count(); ++j) {
+ const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
+ top_level_enum_values.push_back(
+ std::make_pair(value_descriptor.name(), value_descriptor.number()));
+ }
+ }
+
+ for (int i = 0; i < top_level_enum_values.size(); ++i) {
+ printer_->Print("$name$ = $value$\n", "name",
+ ResolveKeyword(top_level_enum_values[i].first), "value",
+ StrCat(top_level_enum_values[i].second));
+ }
+ printer_->Print("\n");
+}
+
+// Prints all enums contained in all message types in |file|.
+void Generator::PrintAllNestedEnumsInFile(
+ StripPrintDescriptor print_mode) const {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ PrintNestedEnums(*file_->message_type(i), print_mode);
+ }
+}
+
+// Prints a Python statement assigning the appropriate module-level
+// enum name to a Python EnumDescriptor object equivalent to
+// enum_descriptor.
+void Generator::PrintCreateEnum(const EnumDescriptor& enum_descriptor) const {
+ std::map<std::string, std::string> m;
+ std::string module_level_descriptor_name =
+ ModuleLevelDescriptorName(enum_descriptor);
+ m["descriptor_name"] = module_level_descriptor_name;
+ m["name"] = enum_descriptor.name();
+ m["full_name"] = enum_descriptor.full_name();
+ m["file"] = kDescriptorKey;
+ const char enum_descriptor_template[] =
+ "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
+ " name='$name$',\n"
+ " full_name='$full_name$',\n"
+ " filename=None,\n"
+ " file=$file$,\n"
+ " create_key=_descriptor._internal_create_key,\n"
+ " values=[\n";
+ std::string options_string;
+ enum_descriptor.options().SerializeToString(&options_string);
+ printer_->Print(m, enum_descriptor_template);
+ printer_->Indent();
+ printer_->Indent();
+
+ if (pure_python_workable_) {
+ for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+ PrintEnumValueDescriptor(*enum_descriptor.value(i));
+ printer_->Print(",\n");
+ }
+ }
+
+ printer_->Outdent();
+ printer_->Print("],\n");
+ printer_->Print("containing_type=None,\n");
+ printer_->Print("serialized_options=$options_value$,\n", "options_value",
+ OptionsValue(options_string));
+ EnumDescriptorProto edp;
+ printer_->Outdent();
+ printer_->Print(")\n");
+ if (pure_python_workable_) {
+ printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
+ module_level_descriptor_name);
+ }
+ printer_->Print("\n");
+}
+
+void Generator::PrintFindEnum(const EnumDescriptor& enum_descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor);
+ m["name"] = enum_descriptor.name();
+ m["file"] = kDescriptorKey;
+ if (enum_descriptor.containing_type()) {
+ m["containing_type"] =
+ ModuleLevelDescriptorName(*enum_descriptor.containing_type());
+ printer_->Print(m,
+ "$descriptor_name$ = "
+ "$containing_type$.enum_types_by_name['$name$']\n");
+ } else {
+ printer_->Print(
+ m, "$descriptor_name$ = $file$.enum_types_by_name['$name$']\n");
+ }
+}
+
+// Recursively prints enums in nested types within descriptor, then
+// prints enums contained at the top level in descriptor.
+void Generator::PrintNestedEnums(const Descriptor& descriptor,
+ StripPrintDescriptor print_mode) const {
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ PrintNestedEnums(*descriptor.nested_type(i), print_mode);
+ }
+
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ if (print_mode == StripPrintDescriptor::kCreate) {
+ PrintCreateEnum(*descriptor.enum_type(i));
+ } else {
+ PrintFindEnum(*descriptor.enum_type(i));
+ }
+ }
+}
+
+void Generator::PrintTopLevelExtensions() const {
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ const FieldDescriptor& extension_field = *file_->extension(i);
+ std::string constant_name = extension_field.name() + "_FIELD_NUMBER";
+ ToUpper(&constant_name);
+ printer_->Print("$constant_name$ = $number$\n", "constant_name",
+ constant_name, "number",
+ StrCat(extension_field.number()));
+ printer_->Print(
+ "$resolved_name$ = "
+ "$file$.extensions_by_name['$name$']\n",
+ "resolved_name", ResolveKeyword(extension_field.name()), "file",
+ kDescriptorKey, "name", extension_field.name());
+ }
+ printer_->Print("\n");
+}
+
+// Prints Python equivalents of all Descriptors in |file|.
+void Generator::PrintMessageDescriptors(StripPrintDescriptor print_mode) const {
+ if (print_mode == StripPrintDescriptor::kCreate) {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ PrintCreateDescriptor(*file_->message_type(i));
+ printer_->Print("\n");
+ }
+ } else {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ PrintFindDescriptor(*file_->message_type(i));
+ }
+ }
+}
+
+void Generator::PrintServiceDescriptors() const {
+ for (int i = 0; i < file_->service_count(); ++i) {
+ PrintServiceDescriptor(*file_->service(i));
+ }
+}
+
+void Generator::PrintServices() const {
+ for (int i = 0; i < file_->service_count(); ++i) {
+ PrintServiceClass(*file_->service(i));
+ PrintServiceStub(*file_->service(i));
+ printer_->Print("\n");
+ }
+}
+
+void Generator::PrintServiceDescriptor(
+ const ServiceDescriptor& descriptor) const {
+ std::map<std::string, std::string> m;
+ m["service_name"] = ModuleLevelServiceDescriptorName(descriptor);
+ m["name"] = descriptor.name();
+ m["file"] = kDescriptorKey;
+ printer_->Print(m, "$service_name$ = $file$.services_by_name['$name$']\n");
+}
+
+void Generator::PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const {
+ std::string name = ModuleLevelServiceDescriptorName(descriptor);
+ if (!pure_python_workable_) {
+ name = "_descriptor.ServiceDescriptor(full_name='" +
+ descriptor.full_name() + "')";
+ }
+ printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key",
+ kDescriptorKey, "descriptor_name", name);
+ std::string module_name = ModuleName(file_->name());
+ printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name);
+}
+
+void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
+ // Print the service.
+ printer_->Print(
+ "$class_name$ = service_reflection.GeneratedServiceType("
+ "'$class_name$', (_service.Service,), dict(\n",
+ "class_name", descriptor.name());
+ printer_->Indent();
+ Generator::PrintDescriptorKeyAndModuleName(descriptor);
+ printer_->Print("))\n\n");
+ printer_->Outdent();
+}
+
+void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
+ // Print the service stub.
+ printer_->Print(
+ "$class_name$_Stub = "
+ "service_reflection.GeneratedServiceStubType("
+ "'$class_name$_Stub', ($class_name$,), dict(\n",
+ "class_name", descriptor.name());
+ printer_->Indent();
+ Generator::PrintDescriptorKeyAndModuleName(descriptor);
+ printer_->Print("))\n\n");
+ printer_->Outdent();
+}
+
+// Prints statement assigning ModuleLevelDescriptorName(message_descriptor)
+// to a Python Descriptor object for message_descriptor.
+//
+// Mutually recursive with PrintNestedDescriptors().
+void Generator::PrintCreateDescriptor(
+ const Descriptor& message_descriptor) const {
+ std::map<std::string, std::string> m;
+ m["name"] = message_descriptor.name();
+ m["full_name"] = message_descriptor.full_name();
+ m["file"] = kDescriptorKey;
+
+ PrintNestedDescriptors(message_descriptor, StripPrintDescriptor::kCreate);
+
+ printer_->Print("\n");
+ printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
+ "descriptor_name",
+ ModuleLevelDescriptorName(message_descriptor));
+ printer_->Indent();
+ const char required_function_arguments[] =
+ "name='$name$',\n"
+ "full_name='$full_name$',\n"
+ "filename=None,\n"
+ "file=$file$,\n"
+ "containing_type=None,\n"
+ "create_key=_descriptor._internal_create_key,\n";
+ printer_->Print(m, required_function_arguments);
+ PrintFieldsInDescriptor(message_descriptor);
+ PrintExtensionsInDescriptor(message_descriptor);
+
+ // Nested types
+ printer_->Print("nested_types=[");
+ for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
+ const std::string nested_name =
+ ModuleLevelDescriptorName(*message_descriptor.nested_type(i));
+ printer_->Print("$name$, ", "name", nested_name);
+ }
+ printer_->Print("],\n");
+
+ // Enum types
+ printer_->Print("enum_types=[\n");
+ printer_->Indent();
+ for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
+ const std::string descriptor_name =
+ ModuleLevelDescriptorName(*message_descriptor.enum_type(i));
+ printer_->Print(descriptor_name.c_str());
+ printer_->Print(",\n");
+ }
+ printer_->Outdent();
+ printer_->Print("],\n");
+ std::string options_string;
+ message_descriptor.options().SerializeToString(&options_string);
+ printer_->Print(
+ "serialized_options=$options_value$,\n"
+ "is_extendable=$extendable$,\n"
+ "syntax='$syntax$'",
+ "options_value", OptionsValue(options_string), "extendable",
+ message_descriptor.extension_range_count() > 0 ? "True" : "False",
+ "syntax", StringifySyntax(message_descriptor.file()->syntax()));
+ printer_->Print(",\n");
+
+ // Extension ranges
+ printer_->Print("extension_ranges=[");
+ for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
+ const Descriptor::ExtensionRange* range =
+ message_descriptor.extension_range(i);
+ printer_->Print("($start$, $end$), ", "start", StrCat(range->start),
+ "end", StrCat(range->end));
+ }
+ printer_->Print("],\n");
+ printer_->Print("oneofs=[\n");
+ printer_->Indent();
+ for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) {
+ const OneofDescriptor* desc = message_descriptor.oneof_decl(i);
+ m.clear();
+ m["name"] = desc->name();
+ m["full_name"] = desc->full_name();
+ m["index"] = StrCat(desc->index());
+ options_string = OptionsValue(desc->options().SerializeAsString());
+ if (options_string == "None") {
+ m["serialized_options"] = "";
+ } else {
+ m["serialized_options"] = ", serialized_options=" + options_string;
+ }
+ printer_->Print(m,
+ "_descriptor.OneofDescriptor(\n"
+ " name='$name$', full_name='$full_name$',\n"
+ " index=$index$, containing_type=None,\n"
+ " create_key=_descriptor._internal_create_key,\n"
+ "fields=[]$serialized_options$),\n");
+ }
+ printer_->Outdent();
+ printer_->Print("],\n");
+
+ printer_->Outdent();
+ printer_->Print(")\n");
+}
+
+void Generator::PrintFindDescriptor(
+ const Descriptor& message_descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
+ m["name"] = message_descriptor.name();
+
+ if (message_descriptor.containing_type()) {
+ m["containing_type"] =
+ ModuleLevelDescriptorName(*message_descriptor.containing_type());
+ printer_->Print(m,
+ "$descriptor_name$ = "
+ "$containing_type$.nested_types_by_name['$name$']\n");
+ } else {
+ m["file"] = kDescriptorKey;
+ printer_->Print(
+ m, "$descriptor_name$ = $file$.message_types_by_name['$name$']\n");
+ }
+
+ PrintNestedDescriptors(message_descriptor, StripPrintDescriptor::kFind);
+}
+
+// Prints Python Descriptor objects for all nested types contained in
+// message_descriptor.
+//
+// Mutually recursive with PrintDescriptor().
+void Generator::PrintNestedDescriptors(const Descriptor& containing_descriptor,
+ StripPrintDescriptor print_mode) const {
+ if (print_mode == StripPrintDescriptor::kCreate) {
+ for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
+ PrintCreateDescriptor(*containing_descriptor.nested_type(i));
+ }
+ } else {
+ for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
+ PrintFindDescriptor(*containing_descriptor.nested_type(i));
+ }
+ }
+}
+
+// Prints all messages in |file|.
+void Generator::PrintMessages() const {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ std::vector<std::string> to_register;
+ PrintMessage(*file_->message_type(i), "", &to_register, false);
+ for (int j = 0; j < to_register.size(); ++j) {
+ printer_->Print("_sym_db.RegisterMessage($name$)\n", "name",
+ ResolveKeyword(to_register[j]));
+ }
+ printer_->Print("\n");
+ }
+}
+
+// Prints a Python class for the given message descriptor. We defer to the
+// metaclass to do almost all of the work of actually creating a useful class.
+// The purpose of this function and its many helper functions above is merely
+// to output a Python version of the descriptors, which the metaclass in
+// reflection.py will use to construct the meat of the class itself.
+//
+// Mutually recursive with PrintNestedMessages().
+// Collect nested message names to_register for the symbol_database.
+void Generator::PrintMessage(const Descriptor& message_descriptor,
+ const std::string& prefix,
+ std::vector<std::string>* to_register,
+ bool is_nested) const {
+ std::string qualified_name;
+ if (is_nested) {
+ if (IsPythonKeyword(message_descriptor.name())) {
+ qualified_name =
+ "getattr(" + prefix + ", '" + message_descriptor.name() + "')";
+ } else {
+ qualified_name = prefix + "." + message_descriptor.name();
+ }
+ printer_->Print(
+ "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', "
+ "(_message.Message,), {\n",
+ "name", message_descriptor.name());
+ } else {
+ qualified_name = ResolveKeyword(message_descriptor.name());
+ printer_->Print(
+ "$qualified_name$ = _reflection.GeneratedProtocolMessageType('$name$', "
+ "(_message.Message,), {\n",
+ "qualified_name", qualified_name, "name", message_descriptor.name());
+ }
+ printer_->Indent();
+
+ to_register->push_back(qualified_name);
+
+ PrintNestedMessages(message_descriptor, qualified_name, to_register);
+ std::map<std::string, std::string> m;
+ m["descriptor_key"] = kDescriptorKey;
+ if (pure_python_workable_) {
+ m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
+ } else {
+ m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
+ message_descriptor.full_name() + "')";
+ }
+ printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n");
+ std::string module_name = ModuleName(file_->name());
+ printer_->Print("'__module__' : '$module_name$'\n", "module_name",
+ module_name);
+ printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", message_descriptor.full_name());
+ printer_->Print("})\n");
+ printer_->Outdent();
+}
+
+// Prints all nested messages within |containing_descriptor|.
+// Mutually recursive with PrintMessage().
+void Generator::PrintNestedMessages(
+ const Descriptor& containing_descriptor, const std::string& prefix,
+ std::vector<std::string>* to_register) const {
+ for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
+ printer_->Print("\n");
+ PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register,
+ true);
+ printer_->Print(",\n");
+ }
+}
+
+// Recursively fixes foreign fields in all nested types in |descriptor|, then
+// sets the message_type and enum_type of all message and enum fields to point
+// to their respective descriptors.
+// Args:
+// descriptor: descriptor to print fields for.
+// containing_descriptor: if descriptor is a nested type, this is its
+// containing type, or NULL if this is a root/top-level type.
+void Generator::FixForeignFieldsInDescriptor(
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const {
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
+ }
+
+ for (int i = 0; i < descriptor.field_count(); ++i) {
+ const FieldDescriptor& field_descriptor = *descriptor.field(i);
+ FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
+ }
+
+ FixContainingTypeInDescriptor(descriptor, containing_descriptor);
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
+ FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
+ }
+ for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
+ std::map<std::string, std::string> m;
+ const OneofDescriptor* oneof = descriptor.oneof_decl(i);
+ m["descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+ m["oneof_name"] = oneof->name();
+ for (int j = 0; j < oneof->field_count(); ++j) {
+ m["field_name"] = oneof->field(j)->name();
+ printer_->Print(
+ m,
+ "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n"
+ " $descriptor_name$.fields_by_name['$field_name$'])\n");
+ printer_->Print(
+ m,
+ "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = "
+ "$descriptor_name$.oneofs_by_name['$oneof_name$']\n");
+ }
+ }
+}
+
+void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["message_name"] = descriptor.name();
+ m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+ const char file_descriptor_template[] =
+ "$descriptor_name$.message_types_by_name['$message_name$'] = "
+ "$message_descriptor_name$\n";
+ printer_->Print(m, file_descriptor_template);
+}
+
+void Generator::AddServiceToFileDescriptor(
+ const ServiceDescriptor& descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["service_name"] = descriptor.name();
+ m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
+ const char file_descriptor_template[] =
+ "$descriptor_name$.services_by_name['$service_name$'] = "
+ "$service_descriptor_name$\n";
+ printer_->Print(m, file_descriptor_template);
+}
+
+void Generator::AddEnumToFileDescriptor(
+ const EnumDescriptor& descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["enum_name"] = descriptor.name();
+ m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+ const char file_descriptor_template[] =
+ "$descriptor_name$.enum_types_by_name['$enum_name$'] = "
+ "$enum_descriptor_name$\n";
+ printer_->Print(m, file_descriptor_template);
+}
+
+void Generator::AddExtensionToFileDescriptor(
+ const FieldDescriptor& descriptor) const {
+ std::map<std::string, std::string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["field_name"] = descriptor.name();
+ m["resolved_name"] = ResolveKeyword(descriptor.name());
+ const char file_descriptor_template[] =
+ "$descriptor_name$.extensions_by_name['$field_name$'] = "
+ "$resolved_name$\n";
+ printer_->Print(m, file_descriptor_template);
+}
+
+// Sets any necessary message_type and enum_type attributes
+// for the Python version of |field|.
+//
+// containing_type may be NULL, in which case this is a module-level field.
+//
+// python_dict_name is the name of the Python dict where we should
+// look the field up in the containing type. (e.g., fields_by_name
+// or extensions_by_name). We ignore python_dict_name if containing_type
+// is NULL.
+void Generator::FixForeignFieldsInField(
+ const Descriptor* containing_type, const FieldDescriptor& field,
+ const std::string& python_dict_name) const {
+ const std::string field_referencing_expression =
+ FieldReferencingExpression(containing_type, field, python_dict_name);
+ std::map<std::string, std::string> m;
+ m["field_ref"] = field_referencing_expression;
+ const Descriptor* foreign_message_type = field.message_type();
+ if (foreign_message_type) {
+ m["foreign_type"] = ModuleLevelDescriptorName(*foreign_message_type);
+ printer_->Print(m, "$field_ref$.message_type = $foreign_type$\n");
+ }
+ const EnumDescriptor* enum_type = field.enum_type();
+ if (enum_type) {
+ m["enum_type"] = ModuleLevelDescriptorName(*enum_type);
+ printer_->Print(m, "$field_ref$.enum_type = $enum_type$\n");
+ }
+}
+
+// Returns the module-level expression for the given FieldDescriptor.
+// Only works for fields in the .proto file this Generator is generating for.
+//
+// containing_type may be NULL, in which case this is a module-level field.
+//
+// python_dict_name is the name of the Python dict where we should
+// look the field up in the containing type. (e.g., fields_by_name
+// or extensions_by_name). We ignore python_dict_name if containing_type
+// is NULL.
+std::string Generator::FieldReferencingExpression(
+ const Descriptor* containing_type, const FieldDescriptor& field,
+ const std::string& python_dict_name) const {
+ // We should only ever be looking up fields in the current file.
+ // The only things we refer to from other files are message descriptors.
+ GOOGLE_CHECK_EQ(field.file(), file_)
+ << field.file()->name() << " vs. " << file_->name();
+ if (!containing_type) {
+ return ResolveKeyword(field.name());
+ }
+ return strings::Substitute("$0.$1['$2']",
+ ModuleLevelDescriptorName(*containing_type),
+ python_dict_name, field.name());
+}
+
+// Prints containing_type for nested descriptors or enum descriptors.
+template <typename DescriptorT>
+void Generator::FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const {
+ if (containing_descriptor != nullptr) {
+ const std::string nested_name = ModuleLevelDescriptorName(descriptor);
+ const std::string parent_name =
+ ModuleLevelDescriptorName(*containing_descriptor);
+ printer_->Print("$nested_name$.containing_type = $parent_name$\n",
+ "nested_name", nested_name, "parent_name", parent_name);
+ }
+}
+
+// Prints statements setting the message_type and enum_type fields in the
+// Python descriptor objects we've already output in the file. We must
+// do this in a separate step due to circular references (otherwise, we'd
+// just set everything in the initial assignment statements).
+void Generator::FixForeignFieldsInDescriptors() const {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ FixForeignFieldsInDescriptor(*file_->message_type(i), nullptr);
+ }
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ AddMessageToFileDescriptor(*file_->message_type(i));
+ }
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ AddEnumToFileDescriptor(*file_->enum_type(i));
+ }
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ AddExtensionToFileDescriptor(*file_->extension(i));
+ }
+
+ // TODO(jieluo): Move this register to PrintFileDescriptor() when
+ // FieldDescriptor.file is added in generated file.
+ printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
+ kDescriptorKey);
+ printer_->Print("\n");
+}
+
+// We need to not only set any necessary message_type fields, but
+// also need to call RegisterExtension() on each message we're
+// extending.
+void Generator::FixForeignFieldsInExtensions() const {
+ // Top-level extensions.
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ FixForeignFieldsInExtension(*file_->extension(i));
+ }
+ // Nested extensions.
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ FixForeignFieldsInNestedExtensions(*file_->message_type(i));
+ }
+ printer_->Print("\n");
+}
+
+void Generator::FixForeignFieldsInExtension(
+ const FieldDescriptor& extension_field) const {
+ GOOGLE_CHECK(extension_field.is_extension());
+
+ std::map<std::string, std::string> m;
+ // Confusingly, for FieldDescriptors that happen to be extensions,
+ // containing_type() means "extended type."
+ // On the other hand, extension_scope() will give us what we normally
+ // mean by containing_type().
+ m["extended_message_class"] =
+ ModuleLevelMessageName(*extension_field.containing_type());
+ m["field"] = FieldReferencingExpression(
+ extension_field.extension_scope(), extension_field, "extensions_by_name");
+ printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n");
+}
+
+void Generator::FixForeignFieldsInNestedExtensions(
+ const Descriptor& descriptor) const {
+ // Recursively fix up extensions in all nested types.
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ FixForeignFieldsInNestedExtensions(*descriptor.nested_type(i));
+ }
+ // Fix up extensions directly contained within this type.
+ for (int i = 0; i < descriptor.extension_count(); ++i) {
+ FixForeignFieldsInExtension(*descriptor.extension(i));
+ }
+}
+
+// Returns a Python expression that instantiates a Python EnumValueDescriptor
+// object for the given C++ descriptor.
+void Generator::PrintEnumValueDescriptor(
+ const EnumValueDescriptor& descriptor) const {
+ // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
+ // More circular references. ::sigh::
+ std::string options_string;
+ descriptor.options().SerializeToString(&options_string);
+ std::map<std::string, std::string> m;
+ m["name"] = descriptor.name();
+ m["index"] = StrCat(descriptor.index());
+ m["number"] = StrCat(descriptor.number());
+ m["options"] = OptionsValue(options_string);
+ printer_->Print(m,
+ "_descriptor.EnumValueDescriptor(\n"
+ " name='$name$', index=$index$, number=$number$,\n"
+ " serialized_options=$options$,\n"
+ " type=None,\n"
+ " create_key=_descriptor._internal_create_key)");
+}
+
+// Returns a CEscaped string of serialized_options.
+std::string Generator::OptionsValue(
+ const std::string& serialized_options) const {
+ if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
+ return "None";
+ } else {
+ return "b'" + CEscape(serialized_options) + "'";
+ }
+}
+
+// Prints an expression for a Python FieldDescriptor for |field|.
+void Generator::PrintFieldDescriptor(const FieldDescriptor& field,
+ bool is_extension) const {
+ std::string options_string;
+ field.options().SerializeToString(&options_string);
+ std::map<std::string, std::string> m;
+ m["name"] = field.name();
+ m["full_name"] = field.full_name();
+ m["index"] = StrCat(field.index());
+ m["number"] = StrCat(field.number());
+ m["type"] = StrCat(field.type());
+ m["cpp_type"] = StrCat(field.cpp_type());
+ m["label"] = StrCat(field.label());
+ m["has_default_value"] = field.has_default_value() ? "True" : "False";
+ m["default_value"] = StringifyDefaultValue(field);
+ m["is_extension"] = is_extension ? "True" : "False";
+ m["serialized_options"] = OptionsValue(options_string);
+ m["json_name"] =
+ field.has_json_name() ? ", json_name='" + field.json_name() + "'" : "";
+ // We always set message_type and enum_type to None at this point, and then
+ // these fields in correctly after all referenced descriptors have been
+ // defined and/or imported (see FixForeignFieldsInDescriptors()).
+ const char field_descriptor_decl[] =
+ "_descriptor.FieldDescriptor(\n"
+ " name='$name$', full_name='$full_name$', index=$index$,\n"
+ " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
+ " has_default_value=$has_default_value$, "
+ "default_value=$default_value$,\n"
+ " message_type=None, enum_type=None, containing_type=None,\n"
+ " is_extension=$is_extension$, extension_scope=None,\n"
+ " serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR,"
+ " create_key=_descriptor._internal_create_key)";
+ printer_->Print(m, field_descriptor_decl);
+}
+
+// Helper for Print{Fields,Extensions}InDescriptor().
+void Generator::PrintFieldDescriptorsInDescriptor(
+ const Descriptor& message_descriptor, bool is_extension,
+ const std::string& list_variable_name, int (Descriptor::*CountFn)() const,
+ const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const {
+ printer_->Print("$list$=[\n", "list", list_variable_name);
+ printer_->Indent();
+ for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) {
+ PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i), is_extension);
+ printer_->Print(",\n");
+ }
+ printer_->Outdent();
+ printer_->Print("],\n");
+}
+
+// Prints a statement assigning "fields" to a list of Python FieldDescriptors,
+// one for each field present in message_descriptor.
+void Generator::PrintFieldsInDescriptor(
+ const Descriptor& message_descriptor) const {
+ const bool is_extension = false;
+ PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, "fields",
+ &Descriptor::field_count,
+ &Descriptor::field);
+}
+
+// Prints a statement assigning "extensions" to a list of Python
+// FieldDescriptors, one for each extension present in message_descriptor.
+void Generator::PrintExtensionsInDescriptor(
+ const Descriptor& message_descriptor) const {
+ const bool is_extension = true;
+ PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension,
+ "extensions", &Descriptor::extension_count,
+ &Descriptor::extension);
+}
+
+bool Generator::GeneratingDescriptorProto() const {
+ return file_->name() == "net/proto2/proto/descriptor.proto" ||
+ file_->name() == "google/protobuf/descriptor.proto";
+}
+
+// Returns the unique Python module-level identifier given to a descriptor.
+// This name is module-qualified iff the given descriptor describes an
+// entity that doesn't come from the current file.
+template <typename DescriptorT>
+std::string Generator::ModuleLevelDescriptorName(
+ const DescriptorT& descriptor) const {
+ // FIXME(robinson):
+ // We currently don't worry about collisions with underscores in the type
+ // names, so these would collide in nasty ways if found in the same file:
+ // OuterProto.ProtoA.ProtoB
+ // OuterProto_ProtoA.ProtoB # Underscore instead of period.
+ // As would these:
+ // OuterProto.ProtoA_.ProtoB
+ // OuterProto.ProtoA._ProtoB # Leading vs. trailing underscore.
+ // (Contrived, but certainly possible).
+ //
+ // The C++ implementation doesn't guard against this either. Leaving
+ // it for now...
+ std::string name = NamePrefixedWithNestedTypes(descriptor, "_");
+ ToUpper(&name);
+ // Module-private for now. Easy to make public later; almost impossible
+ // to make private later.
+ name = "_" + name;
+ // We now have the name relative to its own module. Also qualify with
+ // the module name iff this descriptor is from a different .proto file.
+ if (descriptor.file() != file_) {
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
+ }
+ return name;
+}
+
+// Returns the name of the message class itself, not the descriptor.
+// Like ModuleLevelDescriptorName(), module-qualifies the name iff
+// the given descriptor describes an entity that doesn't come from
+// the current file.
+std::string Generator::ModuleLevelMessageName(
+ const Descriptor& descriptor) const {
+ std::string name = NamePrefixedWithNestedTypes(descriptor, ".");
+ if (descriptor.file() != file_) {
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
+ }
+ return name;
+}
+
+// Returns the unique Python module-level identifier given to a service
+// descriptor.
+std::string Generator::ModuleLevelServiceDescriptorName(
+ const ServiceDescriptor& descriptor) const {
+ std::string name = descriptor.name();
+ ToUpper(&name);
+ name = "_" + name;
+ if (descriptor.file() != file_) {
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
+ }
+ return name;
+}
+
+// Prints standard constructor arguments serialized_start and serialized_end.
+// Args:
+// descriptor: The cpp descriptor to have a serialized reference.
+// proto: A proto
+// Example printer output:
+// serialized_start=41,
+// serialized_end=43,
+//
+template <typename DescriptorT, typename DescriptorProtoT>
+void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor,
+ DescriptorProtoT& proto,
+ const std::string& name) const {
+ descriptor.CopyTo(&proto);
+ std::string sp;
+ proto.SerializeToString(&sp);
+ int offset = file_descriptor_serialized_.find(sp);
+ GOOGLE_CHECK_GE(offset, 0);
+
+ printer_->Print(
+ "$name$._serialized_start=$serialized_start$\n"
+ "$name$._serialized_end=$serialized_end$\n",
+ "name", name, "serialized_start", StrCat(offset), "serialized_end",
+ StrCat(offset + sp.size()));
+}
+
+namespace {
+void PrintDescriptorOptionsFixingCode(const std::string& descriptor,
+ const std::string& options,
+ io::Printer* printer) {
+ // Reset the _options to None thus DescriptorBase.GetOptions() can
+ // parse _options again after extensions are registered.
+ printer->Print(
+ "$descriptor$._options = None\n"
+ "$descriptor$._serialized_options = $serialized_value$\n",
+ "descriptor", descriptor, "serialized_value", options);
+}
+} // namespace
+
+void Generator::SetSerializedPbInterval() const {
+ // Top level enums.
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ EnumDescriptorProto proto;
+ const EnumDescriptor& descriptor = *file_->enum_type(i);
+ PrintSerializedPbInterval(descriptor, proto,
+ ModuleLevelDescriptorName(descriptor));
+ }
+
+ // Messages.
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ SetMessagePbInterval(*file_->message_type(i));
+ }
+
+ // Services.
+ for (int i = 0; i < file_->service_count(); ++i) {
+ ServiceDescriptorProto proto;
+ const ServiceDescriptor& service = *file_->service(i);
+ PrintSerializedPbInterval(service, proto,
+ ModuleLevelServiceDescriptorName(service));
+ }
+}
+
+void Generator::SetMessagePbInterval(const Descriptor& descriptor) const {
+ DescriptorProto message_proto;
+ PrintSerializedPbInterval(descriptor, message_proto,
+ ModuleLevelDescriptorName(descriptor));
+
+ // Nested messages.
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ SetMessagePbInterval(*descriptor.nested_type(i));
+ }
+
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ EnumDescriptorProto proto;
+ const EnumDescriptor& enum_des = *descriptor.enum_type(i);
+ PrintSerializedPbInterval(enum_des, proto,
+ ModuleLevelDescriptorName(enum_des));
+ }
+}
+
+// Prints expressions that set the options field of all descriptors.
+void Generator::FixAllDescriptorOptions() const {
+ // Prints an expression that sets the file descriptor's options.
+ std::string file_options = OptionsValue(file_->options().SerializeAsString());
+ if (file_options != "None") {
+ PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
+ } else {
+ printer_->Print("DESCRIPTOR._options = None\n");
+ }
+ // Prints expressions that set the options for all top level enums.
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+ FixOptionsForEnum(enum_descriptor);
+ }
+ // Prints expressions that set the options for all top level extensions.
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ const FieldDescriptor& field = *file_->extension(i);
+ FixOptionsForField(field);
+ }
+ // Prints expressions that set the options for all messages, nested enums,
+ // nested extensions and message fields.
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ FixOptionsForMessage(*file_->message_type(i));
+ }
+
+ for (int i = 0; i < file_->service_count(); ++i) {
+ FixOptionsForService(*file_->service(i));
+ }
+}
+
+void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
+ std::string oneof_options = OptionsValue(oneof.options().SerializeAsString());
+ if (oneof_options != "None") {
+ std::string oneof_name = strings::Substitute(
+ "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()),
+ "oneofs_by_name", oneof.name());
+ PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_);
+ }
+}
+
+// Prints expressions that set the options for an enum descriptor and its
+// value descriptors.
+void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
+ std::string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
+ std::string enum_options =
+ OptionsValue(enum_descriptor.options().SerializeAsString());
+ if (enum_options != "None") {
+ PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
+ }
+ for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+ const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
+ std::string value_options =
+ OptionsValue(value_descriptor.options().SerializeAsString());
+ if (value_options != "None") {
+ PrintDescriptorOptionsFixingCode(
+ StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
+ value_descriptor.name().c_str()),
+ value_options, printer_);
+ }
+ }
+}
+
+// Prints expressions that set the options for an service descriptor and its
+// value descriptors.
+void Generator::FixOptionsForService(
+ const ServiceDescriptor& service_descriptor) const {
+ std::string descriptor_name =
+ ModuleLevelServiceDescriptorName(service_descriptor);
+ std::string service_options =
+ OptionsValue(service_descriptor.options().SerializeAsString());
+ if (service_options != "None") {
+ PrintDescriptorOptionsFixingCode(descriptor_name, service_options,
+ printer_);
+ }
+
+ for (int i = 0; i < service_descriptor.method_count(); ++i) {
+ const MethodDescriptor* method = service_descriptor.method(i);
+ std::string method_options =
+ OptionsValue(method->options().SerializeAsString());
+ if (method_options != "None") {
+ std::string method_name =
+ descriptor_name + ".methods_by_name['" + method->name() + "']";
+ PrintDescriptorOptionsFixingCode(method_name, method_options, printer_);
+ }
+ }
+}
+
+// Prints expressions that set the options for field descriptors (including
+// extensions).
+void Generator::FixOptionsForField(const FieldDescriptor& field) const {
+ std::string field_options = OptionsValue(field.options().SerializeAsString());
+ if (field_options != "None") {
+ std::string field_name;
+ if (field.is_extension()) {
+ if (field.extension_scope() == nullptr) {
+ // Top level extensions.
+ field_name = field.name();
+ } else {
+ field_name = FieldReferencingExpression(field.extension_scope(), field,
+ "extensions_by_name");
+ }
+ } else {
+ field_name = FieldReferencingExpression(field.containing_type(), field,
+ "fields_by_name");
+ }
+ PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
+ }
+}
+
+// Prints expressions that set the options for a message and all its inner
+// types (nested messages, nested enums, extensions, fields).
+void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
+ // Nested messages.
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ FixOptionsForMessage(*descriptor.nested_type(i));
+ }
+ // Oneofs.
+ for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
+ FixOptionsForOneof(*descriptor.oneof_decl(i));
+ }
+ // Enums.
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ FixOptionsForEnum(*descriptor.enum_type(i));
+ }
+ // Fields.
+ for (int i = 0; i < descriptor.field_count(); ++i) {
+ const FieldDescriptor& field = *descriptor.field(i);
+ FixOptionsForField(field);
+ }
+ // Extensions.
+ for (int i = 0; i < descriptor.extension_count(); ++i) {
+ const FieldDescriptor& field = *descriptor.extension(i);
+ FixOptionsForField(field);
+ }
+ // Message option for this message.
+ std::string message_options =
+ OptionsValue(descriptor.options().SerializeAsString());
+ if (message_options != "None") {
+ std::string descriptor_name = ModuleLevelDescriptorName(descriptor);
+ PrintDescriptorOptionsFixingCode(descriptor_name, message_options,
+ printer_);
+ }
+}
+
+// If a dependency forwards other files through public dependencies, let's
+// copy over the corresponding module aliases.
+void Generator::CopyPublicDependenciesAliases(
+ const std::string& copy_from, const FileDescriptor* file) const {
+ for (int i = 0; i < file->public_dependency_count(); ++i) {
+ std::string module_name = ModuleName(file->public_dependency(i)->name());
+ std::string module_alias = ModuleAlias(file->public_dependency(i)->name());
+ // There's no module alias in the dependent file if it was generated by
+ // an old protoc (less than 3.0.0-alpha-1). Use module name in this
+ // situation.
+ printer_->Print(
+ "try:\n"
+ " $alias$ = $copy_from$.$alias$\n"
+ "except AttributeError:\n"
+ " $alias$ = $copy_from$.$module$\n",
+ "alias", module_alias, "module", module_name, "copy_from", copy_from);
+ CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
+ }
+}
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.h
new file mode 100644
index 00000000..6bcfdda9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_generator.h
@@ -0,0 +1,193 @@
+// 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: robinson@google.com (Will Robinson)
+//
+// Generates Python code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+#include <stubs/mutex.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class EnumValueDescriptor;
+class FieldDescriptor;
+class OneofDescriptor;
+class ServiceDescriptor;
+
+namespace io {
+class Printer;
+}
+
+namespace compiler {
+namespace python {
+
+enum class StripPrintDescriptor { kCreate, kFind };
+
+// CodeGenerator implementation for generated Python protocol buffer classes.
+// If you create your own protocol compiler binary and you want it to support
+// Python output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT Generator : public CodeGenerator {
+ public:
+ Generator();
+ virtual ~Generator();
+
+ // CodeGenerator methods.
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+
+ uint64_t GetSupportedFeatures() const override;
+
+ private:
+ void PrintImports() const;
+ void PrintFileDescriptor() const;
+ void PrintTopLevelEnums() const;
+ void PrintAllNestedEnumsInFile(StripPrintDescriptor print_mode) const;
+ void PrintNestedEnums(const Descriptor& descriptor,
+ StripPrintDescriptor print_mode) const;
+ void PrintCreateEnum(const EnumDescriptor& enum_descriptor) const;
+ void PrintFindEnum(const EnumDescriptor& enum_descriptor) const;
+
+ void PrintTopLevelExtensions() const;
+
+ void PrintFieldDescriptor(const FieldDescriptor& field,
+ bool is_extension) const;
+ void PrintFieldDescriptorsInDescriptor(
+ const Descriptor& message_descriptor, bool is_extension,
+ const std::string& list_variable_name, int (Descriptor::*CountFn)() const,
+ const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const;
+ void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const;
+ void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const;
+ void PrintMessageDescriptors(StripPrintDescriptor print_mode) const;
+ void PrintCreateDescriptor(const Descriptor& message_descriptor) const;
+ void PrintFindDescriptor(const Descriptor& message_descriptor) const;
+ void PrintNestedDescriptors(const Descriptor& containing_descriptor,
+ StripPrintDescriptor print_mode) const;
+
+ void PrintMessages() const;
+ void PrintMessage(const Descriptor& message_descriptor,
+ const std::string& prefix,
+ std::vector<std::string>* to_register,
+ bool is_nested) const;
+ void PrintNestedMessages(const Descriptor& containing_descriptor,
+ const std::string& prefix,
+ std::vector<std::string>* to_register) const;
+
+ void FixForeignFieldsInDescriptors() const;
+ void FixForeignFieldsInDescriptor(
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const;
+ void FixForeignFieldsInField(const Descriptor* containing_type,
+ const FieldDescriptor& field,
+ const std::string& python_dict_name) const;
+ void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
+ void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const;
+ void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const;
+ void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const;
+ std::string FieldReferencingExpression(
+ const Descriptor* containing_type, const FieldDescriptor& field,
+ const std::string& python_dict_name) const;
+ template <typename DescriptorT>
+ void FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const;
+
+ void FixForeignFieldsInExtensions() const;
+ void FixForeignFieldsInExtension(
+ const FieldDescriptor& extension_field) const;
+ void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
+
+ void PrintServices() const;
+ void PrintServiceDescriptors() const;
+ void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
+ void PrintServiceClass(const ServiceDescriptor& descriptor) const;
+ void PrintServiceStub(const ServiceDescriptor& descriptor) const;
+ void PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const;
+
+ void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
+ std::string OptionsValue(const std::string& serialized_options) const;
+ bool GeneratingDescriptorProto() const;
+
+ template <typename DescriptorT>
+ std::string ModuleLevelDescriptorName(const DescriptorT& descriptor) const;
+ std::string ModuleLevelMessageName(const Descriptor& descriptor) const;
+ std::string ModuleLevelServiceDescriptorName(
+ const ServiceDescriptor& descriptor) const;
+
+ template <typename DescriptorT, typename DescriptorProtoT>
+ void PrintSerializedPbInterval(const DescriptorT& descriptor,
+ DescriptorProtoT& proto,
+ const std::string& name) const;
+
+ void FixAllDescriptorOptions() const;
+ void FixOptionsForField(const FieldDescriptor& field) const;
+ void FixOptionsForOneof(const OneofDescriptor& oneof) const;
+ void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
+ void FixOptionsForService(const ServiceDescriptor& descriptor) const;
+ void FixOptionsForMessage(const Descriptor& descriptor) const;
+
+ void SetSerializedPbInterval() const;
+ void SetMessagePbInterval(const Descriptor& descriptor) const;
+
+ void CopyPublicDependenciesAliases(const std::string& copy_from,
+ const FileDescriptor* file) const;
+
+ // Very coarse-grained lock to ensure that Generate() is reentrant.
+ // Guards file_, printer_ and file_descriptor_serialized_.
+ mutable Mutex mutex_;
+ mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_.
+ mutable std::string file_descriptor_serialized_;
+ mutable io::Printer* printer_; // Set in Generate(). Under mutex_.
+ mutable bool pure_python_workable_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
+};
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/python/python_plugin_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_plugin_unittest.cc
new file mode 100644
index 00000000..78b02e92
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/python/python_plugin_unittest.cc
@@ -0,0 +1,161 @@
+// 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>
+
+#include <testing/file.h>
+#include <testing/file.h>
+#include <compiler/command_line_interface.h>
+#include <compiler/python/python_generator.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+#include <stubs/strutil.h>
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+ TestGenerator() {}
+ ~TestGenerator() {}
+
+ virtual bool Generate(const FileDescriptor* file,
+ const std::string& parameter, GeneratorContext* context,
+ std::string* error) const {
+ TryInsert("test_pb2.py", "imports", context);
+ TryInsert("test_pb2.py", "module_scope", context);
+ TryInsert("test_pb2.py", "class_scope:foo.Bar", context);
+ TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context);
+ return true;
+ }
+
+ void TryInsert(const std::string& filename,
+ const std::string& insertion_point,
+ GeneratorContext* context) const {
+ std::unique_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(PythonPluginTest, PluginTest) {
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "message Bar {\n"
+ " message Baz {}\n"
+ "}\n",
+ true));
+
+ compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ python::Generator python_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--python_out", &python_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ std::string proto_path = "-I" + TestTempDir();
+ std::string python_out = "--python_out=" + TestTempDir();
+ std::string test_out = "--test_out=" + TestTempDir();
+
+ const char* argv[] = {"protoc", proto_path.c_str(), python_out.c_str(),
+ test_out.c_str(), "test.proto"};
+
+ EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+// This test verifies that the generated Python output uses regular imports (as
+// opposed to importlib) in the usual case where the .proto file paths do not
+// not contain any Python keywords.
+TEST(PythonPluginTest, ImportTest) {
+ // Create files test1.proto and test2.proto with the former importing the
+ // latter.
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test1.proto",
+ "syntax = \"proto3\";\n"
+ "package foo;\n"
+ "import \"test2.proto\";"
+ "message Message1 {\n"
+ " Message2 message_2 = 1;\n"
+ "}\n",
+ true));
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto",
+ "syntax = \"proto3\";\n"
+ "package foo;\n"
+ "message Message2 {}\n",
+ true));
+
+ compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+ python::Generator python_generator;
+ cli.RegisterGenerator("--python_out", &python_generator, "");
+ std::string proto_path = "-I" + TestTempDir();
+ std::string python_out = "--python_out=" + TestTempDir();
+ const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(),
+ "test1.proto"};
+ ASSERT_EQ(0, cli.Run(5, argv));
+
+ // Loop over the lines of the generated code and verify that we find an
+ // ordinary Python import but do not find the string "importlib".
+ std::string output;
+ GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output,
+ true));
+ std::vector<std::string> lines = Split(output, "\n");
+ std::string expected_import = "import test2_pb2";
+ bool found_expected_import = false;
+ for (int i = 0; i < lines.size(); ++i) {
+ if (lines[i].find(expected_import) != std::string::npos) {
+ found_expected_import = true;
+ }
+ EXPECT_EQ(std::string::npos, lines[i].find("importlib"));
+ }
+ EXPECT_TRUE(found_expected_import);
+}
+
+} // namespace
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto
new file mode 100644
index 00000000..70ec9f17
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto
@@ -0,0 +1,70 @@
+syntax = "proto3";
+
+package A.B.C;
+
+import "ruby_generated_code_proto2_import.proto";
+
+message TestMessage {
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ bool optional_bool = 5;
+ double optional_double = 6;
+ float optional_float = 7;
+ string optional_string = 8;
+ bytes optional_bytes = 9;
+ TestEnum optional_enum = 10;
+ TestMessage optional_msg = 11;
+ TestImportedMessage optional_proto2_submessage = 12;
+
+ repeated int32 repeated_int32 = 21;
+ repeated int64 repeated_int64 = 22;
+ repeated uint32 repeated_uint32 = 23;
+ repeated uint64 repeated_uint64 = 24;
+ repeated bool repeated_bool = 25;
+ repeated double repeated_double = 26;
+ repeated float repeated_float = 27;
+ repeated string repeated_string = 28;
+ repeated bytes repeated_bytes = 29;
+ repeated TestEnum repeated_enum = 30;
+ repeated TestMessage repeated_msg = 31;
+
+ oneof my_oneof {
+ int32 oneof_int32 = 41;
+ int64 oneof_int64 = 42;
+ uint32 oneof_uint32 = 43;
+ uint64 oneof_uint64 = 44;
+ bool oneof_bool = 45;
+ double oneof_double = 46;
+ float oneof_float = 47;
+ string oneof_string = 48;
+ bytes oneof_bytes = 49;
+ TestEnum oneof_enum = 50;
+ TestMessage oneof_msg = 51;
+ }
+
+ map<int32, string> map_int32_string = 61;
+ map<int64, string> map_int64_string = 62;
+ map<uint32, string> map_uint32_string = 63;
+ map<uint64, string> map_uint64_string = 64;
+ map<bool, string> map_bool_string = 65;
+ map<string, string> map_string_string = 66;
+ map<string, TestMessage> map_string_msg = 67;
+ map<string, TestEnum> map_string_enum = 68;
+ map<string, int32> map_string_int32 = 69;
+ map<string, bool> map_string_bool = 70;
+
+ message NestedMessage {
+ int32 foo = 1;
+ }
+
+ NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+ Default = 0;
+ A = 1;
+ B = 2;
+ C = 3;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb
new file mode 100644
index 00000000..256ac7c1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb
@@ -0,0 +1,79 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_code.proto
+
+require 'google/protobuf'
+
+require 'ruby_generated_code_proto2_import_pb'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_file("ruby_generated_code.proto", :syntax => :proto3) do
+ add_message "A.B.C.TestMessage" do
+ optional :optional_int32, :int32, 1
+ optional :optional_int64, :int64, 2
+ optional :optional_uint32, :uint32, 3
+ optional :optional_uint64, :uint64, 4
+ optional :optional_bool, :bool, 5
+ optional :optional_double, :double, 6
+ optional :optional_float, :float, 7
+ optional :optional_string, :string, 8
+ optional :optional_bytes, :bytes, 9
+ optional :optional_enum, :enum, 10, "A.B.C.TestEnum"
+ optional :optional_msg, :message, 11, "A.B.C.TestMessage"
+ optional :optional_proto2_submessage, :message, 12, "A.B.C.TestImportedMessage"
+ repeated :repeated_int32, :int32, 21
+ repeated :repeated_int64, :int64, 22
+ repeated :repeated_uint32, :uint32, 23
+ repeated :repeated_uint64, :uint64, 24
+ repeated :repeated_bool, :bool, 25
+ repeated :repeated_double, :double, 26
+ repeated :repeated_float, :float, 27
+ repeated :repeated_string, :string, 28
+ repeated :repeated_bytes, :bytes, 29
+ repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
+ repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
+ map :map_int32_string, :int32, :string, 61
+ map :map_int64_string, :int64, :string, 62
+ map :map_uint32_string, :uint32, :string, 63
+ map :map_uint64_string, :uint64, :string, 64
+ map :map_bool_string, :bool, :string, 65
+ map :map_string_string, :string, :string, 66
+ map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage"
+ map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum"
+ map :map_string_int32, :string, :int32, 69
+ map :map_string_bool, :string, :bool, 70
+ optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
+ oneof :my_oneof do
+ optional :oneof_int32, :int32, 41
+ optional :oneof_int64, :int64, 42
+ optional :oneof_uint32, :uint32, 43
+ optional :oneof_uint64, :uint64, 44
+ optional :oneof_bool, :bool, 45
+ optional :oneof_double, :double, 46
+ optional :oneof_float, :float, 47
+ optional :oneof_string, :string, 48
+ optional :oneof_bytes, :bytes, 49
+ optional :oneof_enum, :enum, 50, "A.B.C.TestEnum"
+ optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
+ end
+ end
+ add_message "A.B.C.TestMessage.NestedMessage" do
+ optional :foo, :int32, 1
+ end
+ add_enum "A.B.C.TestEnum" do
+ value :Default, 0
+ value :A, 1
+ value :B, 2
+ value :C, 3
+ end
+ end
+end
+
+module A
+ module B
+ module C
+ TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
+ TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
+ TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
+ end
+ end
+end
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto
new file mode 100644
index 00000000..ea7f7836
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto
@@ -0,0 +1,71 @@
+syntax = "proto2";
+
+package A.B.C;
+
+import "ruby_generated_code_proto2_import.proto";
+
+message TestMessage {
+ optional int32 optional_int32 = 1 [default = 1];
+ optional int64 optional_int64 = 2 [default = 2];
+ optional uint32 optional_uint32 = 3 [default = 3];
+ optional uint64 optional_uint64 = 4 [default = 4];
+ optional bool optional_bool = 5 [default = true];
+ optional double optional_double = 6 [default = 6.0];
+ optional float optional_float = 7 [default = 7.0];
+ optional string optional_string = 8 [default = "default str"];
+ optional bytes optional_bytes = 9 [default = "\0\1\2\100fubar"];
+ optional TestEnum optional_enum = 10 [default = A];
+ optional TestMessage optional_msg = 11;
+ optional TestImportedMessage optional_proto2_submessage = 12;
+
+ repeated int32 repeated_int32 = 21;
+ repeated int64 repeated_int64 = 22;
+ repeated uint32 repeated_uint32 = 23;
+ repeated uint64 repeated_uint64 = 24;
+ repeated bool repeated_bool = 25;
+ repeated double repeated_double = 26;
+ repeated float repeated_float = 27;
+ repeated string repeated_string = 28;
+ repeated bytes repeated_bytes = 29;
+ repeated TestEnum repeated_enum = 30;
+ repeated TestMessage repeated_msg = 31;
+
+ required int32 required_int32 = 41;
+ required int64 required_int64 = 42;
+ required uint32 required_uint32 = 43;
+ required uint64 required_uint64 = 44;
+ required bool required_bool = 45;
+ required double required_double = 46;
+ required float required_float = 47;
+ required string required_string = 48;
+ required bytes required_bytes = 49;
+ required TestEnum required_enum = 50;
+ required TestMessage required_msg = 51;
+
+ oneof my_oneof {
+ int32 oneof_int32 = 61;
+ int64 oneof_int64 = 62;
+ uint32 oneof_uint32 = 63;
+ uint64 oneof_uint64 = 64;
+ bool oneof_bool = 65;
+ double oneof_double = 66;
+ float oneof_float = 67;
+ string oneof_string = 68;
+ bytes oneof_bytes = 69;
+ TestEnum oneof_enum = 70;
+ TestMessage oneof_msg = 71;
+ }
+
+ message NestedMessage {
+ optional int32 foo = 1;
+ }
+
+ optional NestedMessage nested_message = 80;
+}
+
+enum TestEnum {
+ Default = 0;
+ A = 1;
+ B = 2;
+ C = 3;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto
new file mode 100644
index 00000000..9ec07381
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto
@@ -0,0 +1,5 @@
+syntax = "proto2";
+
+package A.B.C;
+
+message TestImportedMessage {}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb
new file mode 100644
index 00000000..44d31969
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb
@@ -0,0 +1,80 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_code_proto2.proto
+
+require 'google/protobuf'
+
+require 'ruby_generated_code_proto2_import_pb'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_file("ruby_generated_code_proto2.proto", :syntax => :proto2) do
+ add_message "A.B.C.TestMessage" do
+ optional :optional_int32, :int32, 1, default: 1
+ optional :optional_int64, :int64, 2, default: 2
+ optional :optional_uint32, :uint32, 3, default: 3
+ optional :optional_uint64, :uint64, 4, default: 4
+ optional :optional_bool, :bool, 5, default: true
+ optional :optional_double, :double, 6, default: 6
+ optional :optional_float, :float, 7, default: 7
+ optional :optional_string, :string, 8, default: "default str"
+ optional :optional_bytes, :bytes, 9, default: "\x00\x01\x02\x40\x66\x75\x62\x61\x72".force_encoding("ASCII-8BIT")
+ optional :optional_enum, :enum, 10, "A.B.C.TestEnum", default: 1
+ optional :optional_msg, :message, 11, "A.B.C.TestMessage"
+ optional :optional_proto2_submessage, :message, 12, "A.B.C.TestImportedMessage"
+ repeated :repeated_int32, :int32, 21
+ repeated :repeated_int64, :int64, 22
+ repeated :repeated_uint32, :uint32, 23
+ repeated :repeated_uint64, :uint64, 24
+ repeated :repeated_bool, :bool, 25
+ repeated :repeated_double, :double, 26
+ repeated :repeated_float, :float, 27
+ repeated :repeated_string, :string, 28
+ repeated :repeated_bytes, :bytes, 29
+ repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
+ repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
+ required :required_int32, :int32, 41
+ required :required_int64, :int64, 42
+ required :required_uint32, :uint32, 43
+ required :required_uint64, :uint64, 44
+ required :required_bool, :bool, 45
+ required :required_double, :double, 46
+ required :required_float, :float, 47
+ required :required_string, :string, 48
+ required :required_bytes, :bytes, 49
+ required :required_enum, :enum, 50, "A.B.C.TestEnum"
+ required :required_msg, :message, 51, "A.B.C.TestMessage"
+ optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
+ oneof :my_oneof do
+ optional :oneof_int32, :int32, 61
+ optional :oneof_int64, :int64, 62
+ optional :oneof_uint32, :uint32, 63
+ optional :oneof_uint64, :uint64, 64
+ optional :oneof_bool, :bool, 65
+ optional :oneof_double, :double, 66
+ optional :oneof_float, :float, 67
+ optional :oneof_string, :string, 68
+ optional :oneof_bytes, :bytes, 69
+ optional :oneof_enum, :enum, 70, "A.B.C.TestEnum"
+ optional :oneof_msg, :message, 71, "A.B.C.TestMessage"
+ end
+ end
+ add_message "A.B.C.TestMessage.NestedMessage" do
+ optional :foo, :int32, 1
+ end
+ add_enum "A.B.C.TestEnum" do
+ value :Default, 0
+ value :A, 1
+ value :B, 2
+ value :C, 3
+ end
+ end
+end
+
+module A
+ module B
+ module C
+ TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
+ TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
+ TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
+ end
+ end
+end
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto
new file mode 100644
index 00000000..8d7c948a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto
@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package one.two.a_three;
+
+option ruby_package = "A::B::C";
+
+message Four {
+ string a_string = 1;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto
new file mode 100644
index 00000000..7a0d2608
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto
@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package one.two.a_three.and;
+
+option ruby_package = "AA.BB.CC";
+
+message Four {
+ string another_string = 1;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb
new file mode 100644
index 00000000..cdbbe891
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb
@@ -0,0 +1,20 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_pkg_explicit_legacy.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_file("ruby_generated_pkg_explicit_legacy.proto", :syntax => :proto3) do
+ add_message "one.two.a_three.and.Four" do
+ optional :another_string, :string, 1
+ end
+ end
+end
+
+module AA
+ module BB
+ module CC
+ Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.and.Four").msgclass
+ end
+ end
+end
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb
new file mode 100644
index 00000000..e6d47011
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb
@@ -0,0 +1,20 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_pkg_explicit.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_file("ruby_generated_pkg_explicit.proto", :syntax => :proto3) do
+ add_message "one.two.a_three.Four" do
+ optional :a_string, :string, 1
+ end
+ end
+end
+
+module A
+ module B
+ module C
+ Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass
+ end
+ end
+end
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto
new file mode 100644
index 00000000..544db64d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+package one.two.a_three;
+
+message Four {
+ string a_string = 1;
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb
new file mode 100644
index 00000000..1ac0ef7a
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb
@@ -0,0 +1,20 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ruby_generated_pkg_implicit.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_file("ruby_generated_pkg_implicit.proto", :syntax => :proto3) do
+ add_message "one.two.a_three.Four" do
+ optional :a_string, :string, 1
+ end
+ end
+end
+
+module One
+ module Two
+ module AThree
+ Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass
+ end
+ end
+end
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc
new file mode 100644
index 00000000..7d6d5032
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc
@@ -0,0 +1,575 @@
+// 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 <iomanip>
+#include <sstream>
+
+#include <compiler/code_generator.h>
+#include <compiler/plugin.h>
+#include <descriptor.h>
+#include <descriptor.pb.h>
+#include <io/printer.h>
+#include <io/zero_copy_stream.h>
+
+#include <compiler/ruby/ruby_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+
+// Forward decls.
+template <class numeric_type>
+std::string NumberToString(numeric_type value);
+std::string GetRequireName(const std::string& proto_file);
+std::string LabelForField(FieldDescriptor* field);
+std::string TypeName(FieldDescriptor* field);
+bool GenerateMessage(const Descriptor* message, io::Printer* printer,
+ std::string* error);
+void GenerateEnum(const EnumDescriptor* en, io::Printer* printer);
+void GenerateMessageAssignment(const std::string& prefix,
+ const Descriptor* message, io::Printer* printer);
+void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en,
+ io::Printer* printer);
+std::string DefaultValueForField(const FieldDescriptor* field);
+
+template<class numeric_type>
+std::string NumberToString(numeric_type value) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+}
+
+std::string GetRequireName(const std::string& proto_file) {
+ int lastindex = proto_file.find_last_of(".");
+ return proto_file.substr(0, lastindex) + "_pb";
+}
+
+std::string GetOutputFilename(const std::string& proto_file) {
+ return GetRequireName(proto_file) + ".rb";
+}
+
+std::string LabelForField(const FieldDescriptor* field) {
+ if (field->has_optional_keyword() &&
+ field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return "proto3_optional";
+ }
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_OPTIONAL: return "optional";
+ case FieldDescriptor::LABEL_REQUIRED: return "required";
+ case FieldDescriptor::LABEL_REPEATED: return "repeated";
+ default: assert(false); return "";
+ }
+}
+
+std::string TypeName(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32: return "int32";
+ case FieldDescriptor::TYPE_INT64: return "int64";
+ case FieldDescriptor::TYPE_UINT32: return "uint32";
+ case FieldDescriptor::TYPE_UINT64: return "uint64";
+ case FieldDescriptor::TYPE_SINT32: return "sint32";
+ case FieldDescriptor::TYPE_SINT64: return "sint64";
+ case FieldDescriptor::TYPE_FIXED32: return "fixed32";
+ case FieldDescriptor::TYPE_FIXED64: return "fixed64";
+ case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
+ case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
+ case FieldDescriptor::TYPE_DOUBLE: return "double";
+ case FieldDescriptor::TYPE_FLOAT: return "float";
+ case FieldDescriptor::TYPE_BOOL: return "bool";
+ case FieldDescriptor::TYPE_ENUM: return "enum";
+ case FieldDescriptor::TYPE_STRING: return "string";
+ case FieldDescriptor::TYPE_BYTES: return "bytes";
+ case FieldDescriptor::TYPE_MESSAGE: return "message";
+ case FieldDescriptor::TYPE_GROUP: return "group";
+ default: assert(false); return "";
+ }
+}
+
+std::string StringifySyntax(FileDescriptor::Syntax syntax) {
+ switch (syntax) {
+ case FileDescriptor::SYNTAX_PROTO2:
+ return "proto2";
+ case FileDescriptor::SYNTAX_PROTO3:
+ return "proto3";
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ default:
+ GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports "
+ "proto2 and proto3 syntax.";
+ return "";
+ }
+}
+
+std::string DefaultValueForField(const FieldDescriptor* field) {
+ switch(field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return NumberToString(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_INT64:
+ return NumberToString(field->default_value_int64());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return NumberToString(field->default_value_uint32());
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return NumberToString(field->default_value_uint64());
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return NumberToString(field->default_value_float());
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return NumberToString(field->default_value_double());
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return NumberToString(field->default_value_enum()->number());
+ case FieldDescriptor::CPPTYPE_STRING: {
+ std::ostringstream os;
+ std::string default_str = field->default_value_string();
+
+ if (field->type() == FieldDescriptor::TYPE_STRING) {
+ os << "\"" << default_str << "\"";
+ } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ os << "\"";
+
+ os.fill('0');
+ for (int i = 0; i < default_str.length(); ++i) {
+ // Write the hex form of each byte.
+ os << "\\x" << std::hex << std::setw(2)
+ << ((uint16)((unsigned char)default_str.at(i)));
+ }
+ os << "\".force_encoding(\"ASCII-8BIT\")";
+ }
+
+ return os.str();
+ }
+ default: assert(false); return "";
+ }
+}
+
+void GenerateField(const FieldDescriptor* field, io::Printer* printer) {
+ if (field->is_map()) {
+ const FieldDescriptor* key_field =
+ field->message_type()->FindFieldByNumber(1);
+ const FieldDescriptor* value_field =
+ field->message_type()->FindFieldByNumber(2);
+
+ printer->Print(
+ "map :$name$, :$key_type$, :$value_type$, $number$",
+ "name", field->name(),
+ "key_type", TypeName(key_field),
+ "value_type", TypeName(value_field),
+ "number", NumberToString(field->number()));
+
+ if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->message_type()->full_name());
+ } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->enum_type()->full_name());
+ } else {
+ printer->Print("\n");
+ }
+ } else {
+
+ printer->Print(
+ "$label$ :$name$, ",
+ "label", LabelForField(field),
+ "name", field->name());
+ printer->Print(
+ ":$type$, $number$",
+ "type", TypeName(field),
+ "number", NumberToString(field->number()));
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \"$subtype$\"",
+ "subtype", field->message_type()->full_name());
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \"$subtype$\"",
+ "subtype", field->enum_type()->full_name());
+ }
+
+ if (field->has_default_value()) {
+ printer->Print(", default: $default$", "default",
+ DefaultValueForField(field));
+ }
+
+ if (field->has_json_name()) {
+ printer->Print(", json_name: \"$json_name$\"", "json_name",
+ field->json_name());
+ }
+
+ printer->Print("\n");
+ }
+}
+
+void GenerateOneof(const OneofDescriptor* oneof, io::Printer* printer) {
+ printer->Print(
+ "oneof :$name$ do\n",
+ "name", oneof->name());
+ printer->Indent();
+
+ for (int i = 0; i < oneof->field_count(); i++) {
+ const FieldDescriptor* field = oneof->field(i);
+ GenerateField(field, printer);
+ }
+
+ printer->Outdent();
+ printer->Print("end\n");
+}
+
+bool GenerateMessage(const Descriptor* message, io::Printer* printer,
+ std::string* error) {
+ if (message->extension_range_count() > 0 || message->extension_count() > 0) {
+ GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
+ }
+
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return true;
+ }
+
+ printer->Print(
+ "add_message \"$name$\" do\n",
+ "name", message->full_name());
+ printer->Indent();
+
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ if (!field->real_containing_oneof()) {
+ GenerateField(field, printer);
+ }
+ }
+
+ for (int i = 0; i < message->real_oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ GenerateOneof(oneof, printer);
+ }
+
+ printer->Outdent();
+ printer->Print("end\n");
+
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ if (!GenerateMessage(message->nested_type(i), printer, error)) {
+ return false;
+ }
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnum(message->enum_type(i), printer);
+ }
+
+ return true;
+}
+
+void GenerateEnum(const EnumDescriptor* en, io::Printer* printer) {
+ printer->Print(
+ "add_enum \"$name$\" do\n",
+ "name", en->full_name());
+ printer->Indent();
+
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ printer->Print(
+ "value :$name$, $number$\n",
+ "name", value->name(),
+ "number", NumberToString(value->number()));
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "end\n");
+}
+
+// Locale-agnostic utility functions.
+bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; }
+
+bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; }
+
+bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); }
+
+char UpperChar(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; }
+
+
+// Package names in protobuf are snake_case by convention, but Ruby module
+// names must be PascalCased.
+//
+// foo_bar_baz -> FooBarBaz
+std::string PackageToModule(const std::string& name) {
+ bool next_upper = true;
+ std::string result;
+ result.reserve(name.size());
+
+ for (int i = 0; i < name.size(); i++) {
+ if (name[i] == '_') {
+ next_upper = true;
+ } else {
+ if (next_upper) {
+ result.push_back(UpperChar(name[i]));
+ } else {
+ result.push_back(name[i]);
+ }
+ next_upper = false;
+ }
+ }
+
+ return result;
+}
+
+// Class and enum names in protobuf should be PascalCased by convention, but
+// since there is nothing enforcing this we need to ensure that they are valid
+// Ruby constants. That mainly means making sure that the first character is
+// an upper-case letter.
+std::string RubifyConstant(const std::string& name) {
+ std::string ret = name;
+ if (!ret.empty()) {
+ if (IsLower(ret[0])) {
+ // If it starts with a lowercase letter, capitalize it.
+ ret[0] = UpperChar(ret[0]);
+ } else if (!IsAlpha(ret[0])) {
+ // Otherwise (e.g. if it begins with an underscore), we need to come up
+ // with some prefix that starts with a capital letter. We could be smarter
+ // here, e.g. try to strip leading underscores, but this may cause other
+ // problems if the user really intended the name. So let's just prepend a
+ // well-known suffix.
+ ret = "PB_" + ret;
+ }
+ }
+
+ return ret;
+}
+
+void GenerateMessageAssignment(const std::string& prefix,
+ const Descriptor* message,
+ io::Printer* printer) {
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
+ printer->Print(
+ "$prefix$$name$ = ",
+ "prefix", prefix,
+ "name", RubifyConstant(message->name()));
+ printer->Print(
+ "::Google::Protobuf::DescriptorPool.generated_pool."
+ "lookup(\"$full_name$\").msgclass\n",
+ "full_name", message->full_name());
+
+ std::string nested_prefix = prefix + RubifyConstant(message->name()) + "::";
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer);
+ }
+}
+
+void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en,
+ io::Printer* printer) {
+ printer->Print(
+ "$prefix$$name$ = ",
+ "prefix", prefix,
+ "name", RubifyConstant(en->name()));
+ printer->Print(
+ "::Google::Protobuf::DescriptorPool.generated_pool."
+ "lookup(\"$full_name$\").enummodule\n",
+ "full_name", en->full_name());
+}
+
+int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) {
+ int levels = 0;
+ bool need_change_to_module = true;
+ std::string package_name;
+
+ // Determine the name to use in either format:
+ // proto package: one.two.three
+ // option ruby_package: One::Two::Three
+ if (file->options().has_ruby_package()) {
+ package_name = file->options().ruby_package();
+
+ // If :: is in the package use the Ruby formatted name as-is
+ // -> A::B::C
+ // otherwise, use the dot separator
+ // -> A.B.C
+ if (package_name.find("::") != std::string::npos) {
+ need_change_to_module = false;
+ } else {
+ GOOGLE_LOG(WARNING) << "ruby_package option should be in the form of:"
+ << " 'A::B::C' and not 'A.B.C'";
+ }
+ } else {
+ package_name = file->package();
+ }
+
+ // Use the appropriate delimiter
+ std::string delimiter = need_change_to_module ? "." : "::";
+ int delimiter_size = need_change_to_module ? 1 : 2;
+
+ // Extract each module name and indent
+ while (!package_name.empty()) {
+ size_t dot_index = package_name.find(delimiter);
+ std::string component;
+ if (dot_index == std::string::npos) {
+ component = package_name;
+ package_name = "";
+ } else {
+ component = package_name.substr(0, dot_index);
+ package_name = package_name.substr(dot_index + delimiter_size);
+ }
+ if (need_change_to_module) {
+ component = PackageToModule(component);
+ }
+ printer->Print(
+ "module $name$\n",
+ "name", component);
+ printer->Indent();
+ levels++;
+ }
+ return levels;
+}
+
+void EndPackageModules(int levels, io::Printer* printer) {
+ while (levels > 0) {
+ levels--;
+ printer->Outdent();
+ printer->Print(
+ "end\n");
+ }
+}
+
+bool GenerateDslDescriptor(const FileDescriptor* file, io::Printer* printer,
+ std::string* error) {
+ printer->Print("Google::Protobuf::DescriptorPool.generated_pool.build do\n");
+ printer->Indent();
+ printer->Print("add_file(\"$filename$\", :syntax => :$syntax$) do\n",
+ "filename", file->name(), "syntax",
+ StringifySyntax(file->syntax()));
+ printer->Indent();
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (!GenerateMessage(file->message_type(i), printer, error)) {
+ return false;
+ }
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnum(file->enum_type(i), printer);
+ }
+ printer->Outdent();
+ printer->Print("end\n");
+ printer->Outdent();
+ printer->Print(
+ "end\n\n");
+ return true;
+}
+
+bool GenerateBinaryDescriptor(const FileDescriptor* file, io::Printer* printer,
+ std::string* error) {
+ printer->Print(
+ R"(descriptor_data = File.binread(__FILE__).split("\n__END__\n", 2)[1])");
+ printer->Print(
+ "\nGoogle::Protobuf::DescriptorPool.generated_pool.add_serialized_file("
+ "descriptor_data)\n\n");
+ return true;
+}
+
+bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
+ std::string* error) {
+ printer->Print(
+ "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "# source: $filename$\n"
+ "\n",
+ "filename", file->name());
+
+ printer->Print("require 'google/protobuf'\n\n");
+
+ if (file->dependency_count() != 0) {
+ for (int i = 0; i < file->dependency_count(); i++) {
+ printer->Print("require '$name$'\n", "name", GetRequireName(file->dependency(i)->name()));
+ }
+ printer->Print("\n");
+ }
+
+ // TODO: Remove this when ruby supports extensions for proto2 syntax.
+ if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+ file->extension_count() > 0) {
+ GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
+ }
+
+ bool use_raw_descriptor = file->name() == "google/protobuf/descriptor.proto";
+
+ if (use_raw_descriptor) {
+ GenerateBinaryDescriptor(file, printer, error);
+ } else {
+ GenerateDslDescriptor(file, printer, error);
+ }
+
+ int levels = GeneratePackageModules(file, printer);
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateMessageAssignment("", file->message_type(i), printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnumAssignment("", file->enum_type(i), printer);
+ }
+ EndPackageModules(levels, printer);
+
+ if (use_raw_descriptor) {
+ printer->Print("\n__END__\n");
+ FileDescriptorProto file_proto;
+ file->CopyTo(&file_proto);
+ std::string file_data;
+ file_proto.SerializeToString(&file_data);
+ printer->Print("$raw_descriptor$", "raw_descriptor", file_data);
+ }
+ return true;
+}
+
+bool Generator::Generate(
+ const FileDescriptor* file,
+ const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const {
+
+ if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
+ file->syntax() != FileDescriptor::SYNTAX_PROTO2) {
+ *error = "Invalid or unsupported proto syntax";
+ return false;
+ }
+
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(GetOutputFilename(file->name())));
+ io::Printer printer(output.get(), '$');
+
+ return GenerateFile(file, &printer, error);
+}
+
+} // namespace ruby
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h
new file mode 100644
index 00000000..e8e6e566
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Generates Ruby code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
+
+#include <string>
+
+#include <compiler/code_generator.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+
+// CodeGenerator implementation for generated Ruby protocol buffer classes.
+// If you create your own protocol compiler binary and you want it to support
+// Ruby output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
+class PROTOC_EXPORT Generator : public CodeGenerator {
+ bool Generate(const FileDescriptor* file, const std::string& parameter,
+ GeneratorContext* generator_context,
+ std::string* error) const override;
+ uint64_t GetSupportedFeatures() const override {
+ return FEATURE_PROTO3_OPTIONAL;
+ }
+};
+
+} // namespace ruby
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc
new file mode 100644
index 00000000..cc72c1e6
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -0,0 +1,145 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <memory>
+#include <list>
+
+#include <compiler/ruby/ruby_generator.h>
+#include <compiler/command_line_interface.h>
+#include <io/zero_copy_stream.h>
+#include <io/printer.h>
+
+#include <testing/googletest.h>
+#include <gtest/gtest.h>
+#include <testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace ruby {
+namespace {
+
+std::string FindRubyTestDir() {
+ return TestSourceDir() + "/google/protobuf/compiler/ruby";
+}
+
+// This test is a simple golden-file test over the output of the Ruby code
+// generator. When we make changes to the Ruby extension and alter the Ruby code
+// generator to use those changes, we should (i) manually test the output of the
+// code generator with the extension, and (ii) update the golden output above.
+// Some day, we may integrate build systems between protoc and the language
+// extensions to the point where we can do this test in a more automated way.
+
+void RubyTest(string proto_file, string import_proto_file = "") {
+ std::string ruby_tests = FindRubyTestDir();
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ ruby::Generator ruby_generator;
+ cli.RegisterGenerator("--ruby_out", &ruby_generator, "");
+
+ // Copy generated_code.proto to the temporary test directory.
+ std::string test_input;
+ GOOGLE_CHECK_OK(File::GetContents(
+ ruby_tests + proto_file + ".proto",
+ &test_input,
+ true));
+ GOOGLE_CHECK_OK(File::SetContents(
+ TestTempDir() + proto_file + ".proto",
+ test_input,
+ true));
+
+ // Copy generated_code_import.proto to the temporary test directory.
+ std::string test_import;
+ if (!import_proto_file.empty()) {
+ GOOGLE_CHECK_OK(File::GetContents(
+ ruby_tests + import_proto_file + ".proto",
+ &test_import,
+ true));
+ GOOGLE_CHECK_OK(File::SetContents(
+ TestTempDir() + import_proto_file + ".proto",
+ test_import,
+ true));
+ }
+
+ // Invoke the proto compiler (we will be inside TestTempDir() at this point).
+ std::string ruby_out = "--ruby_out=" + TestTempDir();
+ std::string proto_path = "--proto_path=" + TestTempDir();
+
+ std::string proto_target = TestTempDir() + proto_file + ".proto";
+ const char* argv[] = {
+ "protoc",
+ ruby_out.c_str(),
+ proto_path.c_str(),
+ proto_target.c_str(),
+ };
+
+ EXPECT_EQ(0, cli.Run(4, argv));
+
+ // Load the generated output and compare to the expected result.
+ std::string output;
+ GOOGLE_CHECK_OK(File::GetContentsAsText(
+ TestTempDir() + proto_file + "_pb.rb",
+ &output,
+ true));
+ std::string expected_output;
+ GOOGLE_CHECK_OK(File::GetContentsAsText(
+ ruby_tests + proto_file + "_pb.rb",
+ &expected_output,
+ true));
+ EXPECT_EQ(expected_output, output);
+}
+
+TEST(RubyGeneratorTest, Proto3GeneratorTest) {
+ RubyTest("/ruby_generated_code", "/ruby_generated_code_proto2_import");
+}
+
+TEST(RubyGeneratorTest, Proto2GeneratorTest) {
+ RubyTest("/ruby_generated_code_proto2", "/ruby_generated_code_proto2_import");
+}
+
+TEST(RubyGeneratorTest, Proto3ImplicitPackageTest) {
+ RubyTest("/ruby_generated_pkg_implicit");
+}
+
+TEST(RubyGeneratorTest, Proto3ExplictPackageTest) {
+ RubyTest("/ruby_generated_pkg_explicit");
+}
+
+TEST(RubyGeneratorTest, Proto3ExplictLegacyPackageTest) {
+ RubyTest("/ruby_generated_pkg_explicit_legacy");
+}
+
+} // namespace
+} // namespace ruby
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/scc.h b/NorthstarDedicatedTest/include/protobuf/compiler/scc.h
new file mode 100644
index 00000000..93088bf9
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/scc.h
@@ -0,0 +1,164 @@
+// 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_SCC_H__
+#define GOOGLE_PROTOBUF_COMPILER_SCC_H__
+
+#include <map>
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <descriptor.h>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Description of each strongly connected component. Note that the order
+// of both the descriptors in this SCC and the order of children is
+// deterministic.
+struct SCC {
+ std::vector<const Descriptor*> descriptors;
+ std::vector<const SCC*> children;
+
+ const Descriptor* GetRepresentative() const { return descriptors[0]; }
+
+ // All messages must necessarily be in the same file.
+ const FileDescriptor* GetFile() const { return descriptors[0]->file(); }
+};
+
+// This class is used for analyzing the SCC for each message, to ensure linear
+// instead of quadratic performance, if we do this per message we would get
+// O(V*(V+E)).
+template <class DepsGenerator>
+class PROTOC_EXPORT SCCAnalyzer {
+ public:
+ explicit SCCAnalyzer() : index_(0) {}
+
+ const SCC* GetSCC(const Descriptor* descriptor) {
+ if (cache_.count(descriptor)) return cache_[descriptor].scc;
+ return DFS(descriptor).scc;
+ }
+
+ private:
+ struct NodeData {
+ const SCC* scc; // if null it means its still on the stack
+ int index;
+ int lowlink;
+ };
+
+ std::map<const Descriptor*, NodeData> cache_;
+ std::vector<const Descriptor*> stack_;
+ int index_;
+ std::vector<std::unique_ptr<SCC>> garbage_bin_;
+
+ SCC* CreateSCC() {
+ garbage_bin_.emplace_back(new SCC());
+ return garbage_bin_.back().get();
+ }
+
+ // Tarjan's Strongly Connected Components algo
+ NodeData DFS(const Descriptor* descriptor) {
+ // Must not have visited already.
+ GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0);
+
+ // Mark visited by inserting in map.
+ NodeData& result = cache_[descriptor];
+ // Initialize data structures.
+ result.index = result.lowlink = index_++;
+ stack_.push_back(descriptor);
+
+ // Recurse the fields / nodes in graph
+ for (auto dep : DepsGenerator()(descriptor)) {
+ GOOGLE_CHECK(dep);
+ if (cache_.count(dep) == 0) {
+ // unexplored node
+ NodeData child_data = DFS(dep);
+ result.lowlink = std::min(result.lowlink, child_data.lowlink);
+ } else {
+ NodeData child_data = cache_[dep];
+ if (child_data.scc == nullptr) {
+ // Still in the stack_ so we found a back edge
+ result.lowlink = std::min(result.lowlink, child_data.index);
+ }
+ }
+ }
+ if (result.index == result.lowlink) {
+ // This is the root of a strongly connected component
+ SCC* scc = CreateSCC();
+ while (true) {
+ const Descriptor* scc_desc = stack_.back();
+ scc->descriptors.push_back(scc_desc);
+ // Remove from stack
+ stack_.pop_back();
+ cache_[scc_desc].scc = scc;
+
+ if (scc_desc == descriptor) break;
+ }
+
+ // The order of descriptors is random and depends how this SCC was
+ // discovered. In-order to ensure maximum stability we sort it by name.
+ std::sort(scc->descriptors.begin(), scc->descriptors.end(),
+ [](const Descriptor* a, const Descriptor* b) {
+ return a->full_name() < b->full_name();
+ });
+ AddChildren(scc);
+ }
+ return result;
+ }
+
+ // Add the SCC's that are children of this SCC to its children.
+ void AddChildren(SCC* scc) {
+ std::set<const SCC*> seen;
+ for (auto descriptor : scc->descriptors) {
+ for (auto child_msg : DepsGenerator()(descriptor)) {
+ GOOGLE_CHECK(child_msg);
+ const SCC* child = GetSCC(child_msg);
+ if (child == scc) continue;
+ if (seen.insert(child).second) {
+ scc->children.push_back(child);
+ }
+ }
+ }
+ }
+
+ // This is necessary for compiler bug in msvc2015.
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer);
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.cc b/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.cc
new file mode 100644
index 00000000..84e432cc
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.cc
@@ -0,0 +1,475 @@
+// 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)
+
+#include <compiler/subprocess.h>
+
+#include <algorithm>
+#include <cstring>
+#include <iostream>
+
+#ifndef _WIN32
+#include <errno.h>
+#include <signal.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#endif
+
+#include <stubs/logging.h>
+#include <stubs/common.h>
+#include <message.h>
+#include <stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+char* portable_strdup(const char* s) {
+ char* ns = (char*)malloc(strlen(s) + 1);
+ if (ns != NULL) {
+ strcpy(ns, s);
+ }
+ return ns;
+}
+} // namespace
+
+#ifdef _WIN32
+
+static void CloseHandleOrDie(HANDLE handle) {
+ if (!CloseHandle(handle)) {
+ GOOGLE_LOG(FATAL) << "CloseHandle: "
+ << Subprocess::Win32ErrorMessage(GetLastError());
+ }
+}
+
+Subprocess::Subprocess()
+ : process_start_error_(ERROR_SUCCESS),
+ child_handle_(NULL),
+ child_stdin_(NULL),
+ child_stdout_(NULL) {}
+
+Subprocess::~Subprocess() {
+ if (child_stdin_ != NULL) {
+ CloseHandleOrDie(child_stdin_);
+ }
+ if (child_stdout_ != NULL) {
+ CloseHandleOrDie(child_stdout_);
+ }
+}
+
+void Subprocess::Start(const std::string& program, SearchMode search_mode) {
+ // Create the pipes.
+ HANDLE stdin_pipe_read;
+ HANDLE stdin_pipe_write;
+ HANDLE stdout_pipe_read;
+ HANDLE stdout_pipe_write;
+
+ if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) {
+ GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+ }
+ if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) {
+ GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+ }
+
+ // Make child side of the pipes inheritable.
+ if (!SetHandleInformation(stdin_pipe_read, HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT)) {
+ GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+ << Win32ErrorMessage(GetLastError());
+ }
+ if (!SetHandleInformation(stdout_pipe_write, HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT)) {
+ GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+ << Win32ErrorMessage(GetLastError());
+ }
+
+ // Setup STARTUPINFO to redirect handles.
+ STARTUPINFOA startup_info;
+ ZeroMemory(&startup_info, sizeof(startup_info));
+ startup_info.cb = sizeof(startup_info);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ startup_info.hStdInput = stdin_pipe_read;
+ startup_info.hStdOutput = stdout_pipe_write;
+ startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+ if (startup_info.hStdError == INVALID_HANDLE_VALUE) {
+ GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError());
+ }
+
+ // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'.
+ // Using a malloc'ed string because CreateProcess() can mutate its second
+ // parameter.
+ char* command_line =
+ portable_strdup(("cmd.exe /c \"" + program + "\"").c_str());
+
+ // Create the process.
+ PROCESS_INFORMATION process_info;
+
+ if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
+ (search_mode == SEARCH_PATH) ? command_line : NULL,
+ NULL, // process security attributes
+ NULL, // thread security attributes
+ TRUE, // inherit handles?
+ 0, // obscure creation flags
+ NULL, // environment (inherit from parent)
+ NULL, // current directory (inherit from parent)
+ &startup_info, &process_info)) {
+ child_handle_ = process_info.hProcess;
+ CloseHandleOrDie(process_info.hThread);
+ child_stdin_ = stdin_pipe_write;
+ child_stdout_ = stdout_pipe_read;
+ } else {
+ process_start_error_ = GetLastError();
+ CloseHandleOrDie(stdin_pipe_write);
+ CloseHandleOrDie(stdout_pipe_read);
+ }
+
+ CloseHandleOrDie(stdin_pipe_read);
+ CloseHandleOrDie(stdout_pipe_write);
+ free(command_line);
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+ std::string* error) {
+ if (process_start_error_ != ERROR_SUCCESS) {
+ *error = Win32ErrorMessage(process_start_error_);
+ return false;
+ }
+
+ GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first.";
+
+ std::string input_data = input.SerializeAsString();
+ std::string output_data;
+
+ int input_pos = 0;
+
+ while (child_stdout_ != NULL) {
+ HANDLE handles[2];
+ int handle_count = 0;
+
+ if (child_stdin_ != NULL) {
+ handles[handle_count++] = child_stdin_;
+ }
+ if (child_stdout_ != NULL) {
+ handles[handle_count++] = child_stdout_;
+ }
+
+ DWORD wait_result =
+ WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
+
+ HANDLE signaled_handle = NULL;
+ if (wait_result >= WAIT_OBJECT_0 &&
+ wait_result < WAIT_OBJECT_0 + handle_count) {
+ signaled_handle = handles[wait_result - WAIT_OBJECT_0];
+ } else if (wait_result == WAIT_FAILED) {
+ GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: "
+ << Win32ErrorMessage(GetLastError());
+ } else {
+ GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: "
+ << wait_result;
+ }
+
+ if (signaled_handle == child_stdin_) {
+ DWORD n;
+ if (!WriteFile(child_stdin_, input_data.data() + input_pos,
+ input_data.size() - input_pos, &n, NULL)) {
+ // Child closed pipe. Presumably it will report an error later.
+ // Pretend we're done for now.
+ input_pos = input_data.size();
+ } else {
+ input_pos += n;
+ }
+
+ if (input_pos == input_data.size()) {
+ // We're done writing. Close.
+ CloseHandleOrDie(child_stdin_);
+ child_stdin_ = NULL;
+ }
+ } else if (signaled_handle == child_stdout_) {
+ char buffer[4096];
+ DWORD n;
+
+ if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) {
+ // We're done reading. Close.
+ CloseHandleOrDie(child_stdout_);
+ child_stdout_ = NULL;
+ } else {
+ output_data.append(buffer, n);
+ }
+ }
+ }
+
+ if (child_stdin_ != NULL) {
+ // Child did not finish reading input before it closed the output.
+ // Presumably it exited with an error.
+ CloseHandleOrDie(child_stdin_);
+ child_stdin_ = NULL;
+ }
+
+ DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE);
+
+ if (wait_result == WAIT_FAILED) {
+ GOOGLE_LOG(FATAL) << "WaitForSingleObject: "
+ << Win32ErrorMessage(GetLastError());
+ } else if (wait_result != WAIT_OBJECT_0) {
+ GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: "
+ << wait_result;
+ }
+
+ DWORD exit_code;
+ if (!GetExitCodeProcess(child_handle_, &exit_code)) {
+ GOOGLE_LOG(FATAL) << "GetExitCodeProcess: "
+ << Win32ErrorMessage(GetLastError());
+ }
+
+ CloseHandleOrDie(child_handle_);
+ child_handle_ = NULL;
+
+ if (exit_code != 0) {
+ *error = strings::Substitute("Plugin failed with status code $0.", exit_code);
+ return false;
+ }
+
+ if (!output->ParseFromString(output_data)) {
+ *error = "Plugin output is unparseable: " + CEscape(output_data);
+ return false;
+ }
+
+ return true;
+}
+
+std::string Subprocess::Win32ErrorMessage(DWORD error_code) {
+ char* message;
+
+ // WTF?
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error_code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR)&message, // NOT A BUG!
+ 0, NULL);
+
+ std::string result = message;
+ LocalFree(message);
+ return result;
+}
+
+// ===================================================================
+
+#else // _WIN32
+
+Subprocess::Subprocess()
+ : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {}
+
+Subprocess::~Subprocess() {
+ if (child_stdin_ != -1) {
+ close(child_stdin_);
+ }
+ if (child_stdout_ != -1) {
+ close(child_stdout_);
+ }
+}
+
+void Subprocess::Start(const std::string& program, SearchMode search_mode) {
+ // Note that we assume that there are no other threads, thus we don't have to
+ // do crazy stuff like using socket pairs or avoiding libc locks.
+
+ // [0] is read end, [1] is write end.
+ int stdin_pipe[2];
+ int stdout_pipe[2];
+
+ GOOGLE_CHECK(pipe(stdin_pipe) != -1);
+ GOOGLE_CHECK(pipe(stdout_pipe) != -1);
+
+ char* argv[2] = {portable_strdup(program.c_str()), NULL};
+
+ child_pid_ = fork();
+ if (child_pid_ == -1) {
+ GOOGLE_LOG(FATAL) << "fork: " << strerror(errno);
+ } else if (child_pid_ == 0) {
+ // We are the child.
+ dup2(stdin_pipe[0], STDIN_FILENO);
+ dup2(stdout_pipe[1], STDOUT_FILENO);
+
+ close(stdin_pipe[0]);
+ close(stdin_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+
+ switch (search_mode) {
+ case SEARCH_PATH:
+ execvp(argv[0], argv);
+ break;
+ case EXACT_NAME:
+ execv(argv[0], argv);
+ break;
+ }
+
+ // Write directly to STDERR_FILENO to avoid stdio code paths that may do
+ // stuff that is unsafe here.
+ int ignored;
+ ignored = write(STDERR_FILENO, argv[0], strlen(argv[0]));
+ const char* message =
+ ": program not found or is not executable\n"
+ "Please specify a program using absolute path or make sure "
+ "the program is available in your PATH system variable\n";
+ ignored = write(STDERR_FILENO, message, strlen(message));
+ (void)ignored;
+
+ // Must use _exit() rather than exit() to avoid flushing output buffers
+ // that will also be flushed by the parent.
+ _exit(1);
+ } else {
+ free(argv[0]);
+
+ close(stdin_pipe[0]);
+ close(stdout_pipe[1]);
+
+ child_stdin_ = stdin_pipe[1];
+ child_stdout_ = stdout_pipe[0];
+ }
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+ std::string* error) {
+ GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
+
+ // The "sighandler_t" typedef is GNU-specific, so define our own.
+ typedef void SignalHandler(int);
+
+ // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us.
+ SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN);
+
+ std::string input_data = input.SerializeAsString();
+ std::string output_data;
+
+ int input_pos = 0;
+ int max_fd = std::max(child_stdin_, child_stdout_);
+
+ while (child_stdout_ != -1) {
+ fd_set read_fds;
+ fd_set write_fds;
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+ if (child_stdout_ != -1) {
+ FD_SET(child_stdout_, &read_fds);
+ }
+ if (child_stdin_ != -1) {
+ FD_SET(child_stdin_, &write_fds);
+ }
+
+ if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
+ if (errno == EINTR) {
+ // Interrupted by signal. Try again.
+ continue;
+ } else {
+ GOOGLE_LOG(FATAL) << "select: " << strerror(errno);
+ }
+ }
+
+ if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) {
+ int n = write(child_stdin_, input_data.data() + input_pos,
+ input_data.size() - input_pos);
+ if (n < 0) {
+ // Child closed pipe. Presumably it will report an error later.
+ // Pretend we're done for now.
+ input_pos = input_data.size();
+ } else {
+ input_pos += n;
+ }
+
+ if (input_pos == input_data.size()) {
+ // We're done writing. Close.
+ close(child_stdin_);
+ child_stdin_ = -1;
+ }
+ }
+
+ if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) {
+ char buffer[4096];
+ int n = read(child_stdout_, buffer, sizeof(buffer));
+
+ if (n > 0) {
+ output_data.append(buffer, n);
+ } else {
+ // We're done reading. Close.
+ close(child_stdout_);
+ child_stdout_ = -1;
+ }
+ }
+ }
+
+ if (child_stdin_ != -1) {
+ // Child did not finish reading input before it closed the output.
+ // Presumably it exited with an error.
+ close(child_stdin_);
+ child_stdin_ = -1;
+ }
+
+ int status;
+ while (waitpid(child_pid_, &status, 0) == -1) {
+ if (errno != EINTR) {
+ GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno);
+ }
+ }
+
+ // Restore SIGPIPE handling.
+ signal(SIGPIPE, old_pipe_handler);
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ int error_code = WEXITSTATUS(status);
+ *error =
+ strings::Substitute("Plugin failed with status code $0.", error_code);
+ return false;
+ }
+ } else if (WIFSIGNALED(status)) {
+ int signal = WTERMSIG(status);
+ *error = strings::Substitute("Plugin killed by signal $0.", signal);
+ return false;
+ } else {
+ *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
+ return false;
+ }
+
+ if (!output->ParseFromString(output_data)) {
+ *error = "Plugin output is unparseable: " + CEscape(output_data);
+ return false;
+ }
+
+ return true;
+}
+
+#endif // !_WIN32
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.h b/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.h
new file mode 100644
index 00000000..dfad84e1
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/subprocess.h
@@ -0,0 +1,113 @@
+// 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)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+#define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // right...
+#endif
+#include <windows.h>
+#else // _WIN32
+#include <sys/types.h>
+#include <unistd.h>
+#endif // !_WIN32
+#include <stubs/common.h>
+
+#include <string>
+
+#include <port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace compiler {
+
+// Utility class for launching sub-processes.
+class PROTOC_EXPORT Subprocess {
+ public:
+ Subprocess();
+ ~Subprocess();
+
+ enum SearchMode {
+ SEARCH_PATH, // Use PATH environment variable.
+ EXACT_NAME // Program is an exact file name; don't use the PATH.
+ };
+
+ // Start the subprocess. Currently we don't provide a way to specify
+ // arguments as protoc plugins don't have any.
+ void Start(const std::string& program, SearchMode search_mode);
+
+ // Serialize the input message and pipe it to the subprocess's stdin, then
+ // close the pipe. Meanwhile, read from the subprocess's stdout and parse
+ // the data into *output. All this is done carefully to avoid deadlocks.
+ // Returns true if successful. On any sort of error, returns false and sets
+ // *error to a description of the problem.
+ bool Communicate(const Message& input, Message* output, std::string* error);
+
+#ifdef _WIN32
+ // Given an error code, returns a human-readable error message. This is
+ // defined here so that CommandLineInterface can share it.
+ static std::string Win32ErrorMessage(DWORD error_code);
+#endif
+
+ private:
+#ifdef _WIN32
+ DWORD process_start_error_;
+ HANDLE child_handle_;
+
+ // The file handles for our end of the child's pipes. We close each and
+ // set it to NULL when no longer needed.
+ HANDLE child_stdin_;
+ HANDLE child_stdout_;
+
+#else // _WIN32
+ pid_t child_pid_;
+
+ // The file descriptors for our end of the child's pipes. We close each and
+ // set it to -1 when no longer needed.
+ int child_stdin_;
+ int child_stdout_;
+
+#endif // !_WIN32
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/test_plugin.cc b/NorthstarDedicatedTest/include/protobuf/compiler/test_plugin.cc
new file mode 100644
index 00000000..bca1f068
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/test_plugin.cc
@@ -0,0 +1,61 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is a dummy code generator plugin used by
+// command_line_interface_unittest.
+
+#include <stdlib.h>
+#include <string>
+#include <compiler/mock_code_generator.h>
+#include <compiler/plugin.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+int ProtobufMain(int argc, char* argv[]) {
+ MockCodeGenerator generator("test_plugin");
+ return PluginMain(argc, argv, &generator);
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+int main(int argc, char* argv[]) {
+#ifdef _MSC_VER
+ // Don't print a silly message or stick a modal dialog box in my face,
+ // please.
+ _set_abort_behavior(0, ~0);
+#endif // !_MSC_VER
+ return google::protobuf::compiler::ProtobufMain(argc, argv);
+}
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/zip_output_unittest.sh b/NorthstarDedicatedTest/include/protobuf/compiler/zip_output_unittest.sh
new file mode 100644
index 00000000..f8597912
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/zip_output_unittest.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2009 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (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)
+#
+# Test protoc's zip output mode.
+
+fail() {
+ echo "$@" >&2
+ exit 1
+}
+
+TEST_TMPDIR=.
+PROTOC=./protoc
+JAR=jar
+UNZIP=unzip
+
+echo '
+ syntax = "proto2";
+ option java_multiple_files = true;
+ option java_package = "test.jar";
+ option java_outer_classname = "Outer";
+ message Foo {}
+ message Bar {}
+' > $TEST_TMPDIR/testzip.proto
+
+$PROTOC \
+ --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \
+ --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \
+ || fail 'protoc failed.'
+
+echo "Testing output to zip..."
+if $UNZIP -h > /dev/null; then
+ $UNZIP -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list \
+ || fail 'unzip failed.'
+
+ grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'testzip.pb.cc not found in output zip.'
+ grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'testzip.pb.h not found in output zip.'
+ grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'testzip_pb2.py not found in output zip.'
+ grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \
+ && fail 'Zip file contained manifest.'
+else
+ echo "Warning: 'unzip' command not available. Skipping test."
+fi
+
+echo "Testing output to jar..."
+if $JAR c $TEST_TMPDIR/testzip.proto > /dev/null; then
+ $JAR tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list \
+ || fail 'jar failed.'
+
+ # Check that -interface.jar timestamps are normalized:
+ if [[ "$(TZ=UTC $JAR tvf $TEST_TMPDIR/testzip.jar)" != *'Tue Jan 01 00:00:00 UTC 1980'* ]]; then
+ fail 'Zip did not contain normalized timestamps'
+ fi
+
+ grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'Foo.java not found in output jar.'
+ grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'Bar.java not found in output jar.'
+ grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'Outer.java not found in output jar.'
+ grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \
+ || fail 'Manifest not found in output jar.'
+else
+ echo "Warning: 'jar' command not available. Skipping test."
+fi
+
+echo PASS
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.cc b/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.cc
new file mode 100644
index 00000000..b2361dae
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.cc
@@ -0,0 +1,195 @@
+// 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: ambrose@google.com (Ambrose Feinstein),
+// kenton@google.com (Kenton Varda)
+//
+// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+#include <compiler/zip_writer.h>
+
+#include <cstdint>
+
+#include <io/coded_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// January 1, 1980 as a DOS date.
+// see https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
+static const uint16_t kDosEpoch = 1 << 5 | 1;
+
+static const uint32_t kCRC32Table[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+
+static uint32_t ComputeCRC32(const std::string& buf) {
+ uint32_t x = ~0U;
+ for (int i = 0; i < buf.size(); ++i) {
+ unsigned char c = buf[i];
+ x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
+ }
+ return ~x;
+}
+
+static void WriteShort(io::CodedOutputStream* out, uint16_t val) {
+ uint8_t p[2];
+ p[0] = static_cast<uint8_t>(val);
+ p[1] = static_cast<uint8_t>(val >> 8);
+ out->WriteRaw(p, 2);
+}
+
+ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output)
+ : raw_output_(raw_output) {}
+ZipWriter::~ZipWriter() {}
+
+bool ZipWriter::Write(const std::string& filename,
+ const std::string& contents) {
+ FileInfo info;
+
+ info.name = filename;
+ uint16_t filename_size = filename.size();
+ info.offset = raw_output_->ByteCount();
+ info.size = contents.size();
+ info.crc32 = ComputeCRC32(contents);
+
+ files_.push_back(info);
+
+ // write file header
+ io::CodedOutputStream output(raw_output_);
+ output.WriteLittleEndian32(0x04034b50); // magic
+ WriteShort(&output, 10); // version needed to extract
+ WriteShort(&output, 0); // flags
+ WriteShort(&output, 0); // compression method: stored
+ WriteShort(&output, 0); // last modified time
+ WriteShort(&output, kDosEpoch); // last modified date
+ output.WriteLittleEndian32(info.crc32); // crc-32
+ output.WriteLittleEndian32(info.size); // compressed size
+ output.WriteLittleEndian32(info.size); // uncompressed size
+ WriteShort(&output, filename_size); // file name length
+ WriteShort(&output, 0); // extra field length
+ output.WriteString(filename); // file name
+ output.WriteString(contents); // file data
+
+ return !output.HadError();
+}
+
+bool ZipWriter::WriteDirectory() {
+ uint16_t num_entries = files_.size();
+ uint32_t dir_ofs = raw_output_->ByteCount();
+
+ // write central directory
+ io::CodedOutputStream output(raw_output_);
+ for (int i = 0; i < num_entries; ++i) {
+ const std::string& filename = files_[i].name;
+ uint16_t filename_size = filename.size();
+ uint32_t crc32 = files_[i].crc32;
+ uint32_t size = files_[i].size;
+ uint32_t offset = files_[i].offset;
+
+ output.WriteLittleEndian32(0x02014b50); // magic
+ WriteShort(&output, 10); // version made by
+ WriteShort(&output, 10); // version needed to extract
+ WriteShort(&output, 0); // flags
+ WriteShort(&output, 0); // compression method: stored
+ WriteShort(&output, 0); // last modified time
+ WriteShort(&output, kDosEpoch); // last modified date
+ output.WriteLittleEndian32(crc32); // crc-32
+ output.WriteLittleEndian32(size); // compressed size
+ output.WriteLittleEndian32(size); // uncompressed size
+ WriteShort(&output, filename_size); // file name length
+ WriteShort(&output, 0); // extra field length
+ WriteShort(&output, 0); // file comment length
+ WriteShort(&output, 0); // starting disk number
+ WriteShort(&output, 0); // internal file attributes
+ output.WriteLittleEndian32(0); // external file attributes
+ output.WriteLittleEndian32(offset); // local header offset
+ output.WriteString(filename); // file name
+ }
+ uint32_t dir_len = output.ByteCount();
+
+ // write end of central directory marker
+ output.WriteLittleEndian32(0x06054b50); // magic
+ WriteShort(&output, 0); // disk number
+ WriteShort(&output, 0); // disk with start of central directory
+ WriteShort(&output, num_entries); // central directory entries (this disk)
+ WriteShort(&output, num_entries); // central directory entries (total)
+ output.WriteLittleEndian32(dir_len); // central directory byte size
+ output.WriteLittleEndian32(dir_ofs); // central directory offset
+ WriteShort(&output, 0); // comment length
+
+ return output.HadError();
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.h b/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.h
new file mode 100644
index 00000000..243bbf1d
--- /dev/null
+++ b/NorthstarDedicatedTest/include/protobuf/compiler/zip_writer.h
@@ -0,0 +1,65 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <cstdint>
+#include <vector>
+
+#include <stubs/common.h>
+#include <io/zero_copy_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class ZipWriter {
+ public:
+ ZipWriter(io::ZeroCopyOutputStream* raw_output);
+ ~ZipWriter();
+
+ bool Write(const std::string& filename, const std::string& contents);
+ bool WriteDirectory();
+
+ private:
+ struct FileInfo {
+ std::string name;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t crc32;
+ };
+
+ io::ZeroCopyOutputStream* raw_output_;
+ std::vector<FileInfo> files_;
+};
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google