aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf')
-rw-r--r--src/google/protobuf/any.cc46
-rw-r--r--src/google/protobuf/any.h18
-rw-r--r--src/google/protobuf/any.pb.cc24
-rw-r--r--src/google/protobuf/any.pb.h4
-rw-r--r--src/google/protobuf/any.proto39
-rw-r--r--src/google/protobuf/api.pb.cc46
-rw-r--r--src/google/protobuf/api.pb.h8
-rwxr-xr-xsrc/google/protobuf/arena.cc15
-rw-r--r--src/google/protobuf/arena.h20
-rw-r--r--src/google/protobuf/arena_nc_test.py2
-rw-r--r--src/google/protobuf/arena_unittest.cc58
-rwxr-xr-xsrc/google/protobuf/arenastring.h3
-rw-r--r--src/google/protobuf/arenastring_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc17
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h1
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc42
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc46
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h11
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc191
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc40
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc69
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h85
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc65
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc357
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc100
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_options.h12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc35
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc93
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h12
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/metadata_test.cc186
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.cc24
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.cc11
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.h8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc18
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc31
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc20
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.cc129
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h24
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.cc11
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc21
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc14
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.h8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_options.h86
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc9
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.h10
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_reflection_class.cc10
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_reflection_class.h6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc10
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc13
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_source_generator_base.h6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc11
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.h10
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_context.cc9
-rw-r--r--src/google/protobuf/compiler/java/java_context.h16
-rw-r--r--src/google/protobuf/compiler/java/java_doc_comment.cc56
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc84
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc29
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc110
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.h6
-rw-r--r--src/google/protobuf/compiler/java/java_enum_lite.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc87
-rw-r--r--src/google/protobuf/compiler/java/java_extension_lite.cc118
-rw-r--r--src/google/protobuf/compiler/java/java_extension_lite.h76
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc12
-rw-r--r--src/google/protobuf/compiler/java/java_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc35
-rw-r--r--src/google/protobuf/compiler/java/java_file.h3
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc16
-rw-r--r--src/google/protobuf/compiler/java/java_generator_factory.cc14
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h39
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc32
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.h4
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc32
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.h2
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc179
-rw-r--r--src/google/protobuf/compiler/java/java_message.h10
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc11
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder_lite.cc19
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc57
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.h6
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc352
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.h8
-rw-r--r--src/google/protobuf/compiler/java/java_name_resolver.cc7
-rw-r--r--src/google/protobuf/compiler/java/java_name_resolver.h1
-rw-r--r--src/google/protobuf/compiler/java/java_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc12
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.cc63
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.h6
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc7
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.h5
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc30
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.cc66
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.h6
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc8
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc8
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc780
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.h18
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc12
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.h5
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.cc71
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc17
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.h2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc8
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc157
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.h20
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc12
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc60
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h20
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc14
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.h1
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc257
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.cc15
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.h4
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc26
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h5
-rw-r--r--src/google/protobuf/compiler/plugin.cc81
-rw-r--r--src/google/protobuf/compiler/plugin.h18
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc36
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h6
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc4
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/subprocess.cc2
-rw-r--r--src/google/protobuf/descriptor.cc33
-rw-r--r--src/google/protobuf/descriptor.h26
-rw-r--r--src/google/protobuf/descriptor.pb.cc530
-rw-r--r--src/google/protobuf/descriptor.pb.h169
-rw-r--r--src/google/protobuf/descriptor.proto6
-rw-r--r--src/google/protobuf/descriptor_unittest.cc13
-rw-r--r--src/google/protobuf/duration.pb.cc25
-rw-r--r--src/google/protobuf/duration.proto2
-rw-r--r--src/google/protobuf/dynamic_message.cc20
-rw-r--r--src/google/protobuf/empty.pb.cc17
-rw-r--r--src/google/protobuf/empty.proto1
-rw-r--r--src/google/protobuf/field_mask.pb.cc11
-rw-r--r--src/google/protobuf/field_mask.pb.h1
-rw-r--r--src/google/protobuf/field_mask.proto28
-rw-r--r--src/google/protobuf/generated_message_reflection.cc54
-rw-r--r--src/google/protobuf/generated_message_reflection.h12
-rw-r--r--src/google/protobuf/generated_message_util.h4
-rw-r--r--src/google/protobuf/io/coded_stream.cc10
-rw-r--r--src/google/protobuf/io/coded_stream.h2
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc2
-rw-r--r--src/google/protobuf/io/gzip_stream.h3
-rw-r--r--src/google/protobuf/io/printer.cc76
-rw-r--r--src/google/protobuf/io/printer.h164
-rw-r--r--src/google/protobuf/io/printer_unittest.cc237
-rw-r--r--src/google/protobuf/io/tokenizer.cc8
-rw-r--r--src/google/protobuf/io/tokenizer.h20
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc18
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.cc20
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h3
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc4
-rw-r--r--src/google/protobuf/lite_unittest.cc27
-rw-r--r--src/google/protobuf/map.h1105
-rw-r--r--src/google/protobuf/map_field.cc25
-rw-r--r--src/google/protobuf/map_field.h7
-rw-r--r--src/google/protobuf/map_field_inl.h20
-rw-r--r--src/google/protobuf/map_field_test.cc2
-rw-r--r--src/google/protobuf/map_test.cc389
-rw-r--r--src/google/protobuf/message.cc4
-rw-r--r--src/google/protobuf/message_lite.cc21
-rw-r--r--src/google/protobuf/message_unittest.cc1
-rw-r--r--src/google/protobuf/metadata.h2
-rw-r--r--src/google/protobuf/proto3_arena_lite_unittest.cc164
-rw-r--r--src/google/protobuf/proto3_lite_unittest.cc145
-rw-r--r--src/google/protobuf/repeated_field.cc4
-rw-r--r--src/google/protobuf/repeated_field.h119
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc38
-rw-r--r--src/google/protobuf/source_context.pb.cc11
-rw-r--r--src/google/protobuf/source_context.pb.h1
-rw-r--r--src/google/protobuf/struct.pb.cc42
-rw-r--r--src/google/protobuf/struct.pb.h3
-rw-r--r--src/google/protobuf/struct.proto3
-rwxr-xr-xsrc/google/protobuf/stubs/hash.h12
-rw-r--r--src/google/protobuf/stubs/int128.cc2
-rw-r--r--src/google/protobuf/stubs/logging.h2
-rw-r--r--src/google/protobuf/stubs/mathutil.h2
-rw-r--r--src/google/protobuf/stubs/statusor.h2
-rw-r--r--src/google/protobuf/stubs/stringpiece.h38
-rw-r--r--src/google/protobuf/stubs/stringprintf.cc1
-rw-r--r--src/google/protobuf/stubs/strutil.h8
-rw-r--r--src/google/protobuf/text_format.cc27
-rw-r--r--src/google/protobuf/text_format_unittest.cc4
-rw-r--r--src/google/protobuf/timestamp.pb.cc25
-rw-r--r--src/google/protobuf/timestamp.proto1
-rw-r--r--src/google/protobuf/type.pb.cc70
-rw-r--r--src/google/protobuf/type.pb.h81
-rw-r--r--src/google/protobuf/unittest.proto1
-rw-r--r--src/google/protobuf/unittest_lite.proto22
-rw-r--r--src/google/protobuf/unittest_proto3_arena_lite.proto207
-rw-r--r--src/google/protobuf/unittest_proto3_lite.proto206
-rw-r--r--src/google/protobuf/util/field_comparator.cc22
-rw-r--r--src/google/protobuf/util/field_comparator.h4
-rw-r--r--src/google/protobuf/util/field_comparator_test.cc1
-rw-r--r--src/google/protobuf/util/field_mask_util.cc76
-rw-r--r--src/google/protobuf/util/field_mask_util.h40
-rw-r--r--src/google/protobuf/util/field_mask_util_test.cc114
-rw-r--r--src/google/protobuf/util/internal/constants.h20
-rw-r--r--src/google/protobuf/util/internal/datapiece.cc46
-rw-r--r--src/google/protobuf/util/internal/datapiece.h41
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc64
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h50
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.cc20
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.h15
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter_test.cc26
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.cc62
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser_test.cc119
-rw-r--r--src/google/protobuf/util/internal/object_writer.h19
-rw-r--r--src/google/protobuf/util/internal/proto_writer.cc124
-rw-r--r--src/google/protobuf/util/internal/proto_writer.h21
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.cc75
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.h50
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource_test.cc179
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc143
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h36
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc414
-rw-r--r--src/google/protobuf/util/internal/testdata/books.proto16
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.cc6
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.h8
-rw-r--r--src/google/protobuf/util/internal/utility.cc7
-rw-r--r--src/google/protobuf/util/json_util.cc40
-rw-r--r--src/google/protobuf/util/json_util_test.cc68
-rw-r--r--src/google/protobuf/util/message_differencer.cc11
-rw-r--r--src/google/protobuf/wire_format_lite.cc8
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h6
-rw-r--r--src/google/protobuf/wire_format_unittest.cc1
-rw-r--r--src/google/protobuf/wrappers.pb.cc107
-rw-r--r--src/google/protobuf/wrappers.pb.h8
-rw-r--r--src/google/protobuf/wrappers.proto1
253 files changed, 9091 insertions, 2952 deletions
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index f3ca06bf..f7b1d310 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -35,10 +35,15 @@ namespace protobuf {
namespace internal {
namespace {
-string GetTypeUrl(const Descriptor* message) {
- return string(kTypeGoogleApisComPrefix) + message->full_name();
+string GetTypeUrl(const Descriptor* message,
+ const string& type_url_prefix) {
+ if (!type_url_prefix.empty() &&
+ type_url_prefix[type_url_prefix.size() - 1] == '/') {
+ return type_url_prefix + message->full_name();
+ } else {
+ return type_url_prefix + "/" + message->full_name();
+ }
}
-
} // namespace
const char kAnyFullTypeName[] = "google.protobuf.Any";
@@ -50,8 +55,13 @@ AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
}
void AnyMetadata::PackFrom(const Message& message) {
+ PackFrom(message, kTypeGoogleApisComPrefix);
+}
+
+void AnyMetadata::PackFrom(const Message& message,
+ const string& type_url_prefix) {
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
- GetTypeUrl(message.GetDescriptor()));
+ GetTypeUrl(message.GetDescriptor(), type_url_prefix));
message.SerializeToString(value_->MutableNoArena(
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
}
@@ -67,30 +77,20 @@ bool AnyMetadata::UnpackTo(Message* message) const {
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
const string type_url = type_url_->GetNoArena(
&::google::protobuf::internal::GetEmptyString());
- const string full_name = descriptor->full_name();
- if (type_url.length() < full_name.length()) {
- return false;
+ string full_name;
+ if (!ParseAnyTypeUrl(type_url, &full_name)) {
+ return false;
}
- return (0 == type_url.compare(
- type_url.length() - full_name.length(),
- full_name.length(),
- full_name));
+ return full_name == descriptor->full_name();
}
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
- static const char* prefix[] = {
- kTypeGoogleApisComPrefix,
- kTypeGoogleProdComPrefix
- };
- for (int i = 0; i < 2; i++) {
- const int prefix_len = strlen(prefix[i]);
- if (strncmp(type_url.c_str(), prefix[i], prefix_len) == 0) {
- full_type_name->assign(type_url.data() + prefix_len,
- type_url.size() - prefix_len);
- return true;
- }
+ size_t pos = type_url.find_last_of("/");
+ if (pos == string::npos || pos + 1 == type_url.size()) {
+ return false;
}
- return false;
+ *full_type_name = type_url.substr(pos + 1);
+ return true;
}
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index c8dbef13..04e54166 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -50,10 +50,26 @@ class LIBPROTOBUF_EXPORT AnyMetadata {
// AnyMetadata does not take ownership of "type_url" and "value".
AnyMetadata(UrlType* type_url, ValueType* value);
+ // Packs a message using the default type URL prefix: "type.googleapis.com".
+ // The resulted type URL will be "type.googleapis.com/<message_full_name>".
void PackFrom(const Message& message);
-
+ // Packs a message using the given type URL prefix. The type URL will be
+ // constructed by concatenating the message type's full name to the prefix
+ // with an optional "/" separator if the prefix doesn't already end up "/".
+ // For example, both PackFrom(message, "type.googleapis.com") and
+ // PackFrom(message, "type.googleapis.com/") yield the same result type
+ // URL: "type.googleapis.com/<message_full_name>".
+ void PackFrom(const Message& message, const string& type_url_prefix);
+
+ // Unpacks the payload into the given message. Returns false if the message's
+ // type doesn't match the type specified in the type URL (i.e., the full
+ // name after the last "/" of the type URL doesn't match the message's actaul
+ // full name) or parsing the payload has failed.
bool UnpackTo(Message* message) const;
+ // Checks whether the type specified in the type URL matches the given type.
+ // A type is consdiered matching if its full name matches the full name after
+ // the last "/" in the type URL.
template<typename T>
bool Is() const {
return InternalIs(T::default_instance().GetDescriptor());
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 0bf523b3..fbde4a6d 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -83,9 +83,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\031google/protobuf/any.proto\022\017google.prot"
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
- " \001(\014BK\n\023com.google.protobufB\010AnyProtoP\001\240"
- "\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownType"
- "sb\006proto3", 169);
+ " \001(\014Br\n\023com.google.protobufB\010AnyProtoP\001Z"
+ "%github.com/golang/protobuf/ptypes/any\240\001"
+ "\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes"
+ "b\006proto3", 208);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/any.proto", &protobuf_RegisterTypes);
Any::default_instance_ = new Any();
@@ -116,6 +117,11 @@ void Any::PackFrom(const ::google::protobuf::Message& message) {
_any_metadata_.PackFrom(message);
}
+void Any::PackFrom(const ::google::protobuf::Message& message,
+ const ::std::string& type_url_prefix) {
+ _any_metadata_.PackFrom(message, type_url_prefix);
+}
+
bool Any::UnpackTo(::google::protobuf::Message* message) const {
return _any_metadata_.UnpackTo(message);
}
@@ -190,13 +196,14 @@ Any* Any::New(::google::protobuf::Arena* arena) const {
}
void Any::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
bool Any::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
for (;;) {
@@ -302,6 +309,7 @@ void Any::SerializeWithCachedSizes(
}
int Any::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
int total_size = 0;
// optional string type_url = 1;
@@ -325,18 +333,22 @@ int Any::ByteSize() const {
}
void Any::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Any* source =
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
MergeFrom(*source);
}
}
void Any::MergeFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.type_url().size() > 0) {
@@ -349,12 +361,14 @@ void Any::MergeFrom(const Any& from) {
}
void Any::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Any::CopyFrom(const Any& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -417,6 +431,7 @@ void Any::clear_type_url() {
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Any::release_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -460,6 +475,7 @@ void Any::clear_value() {
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Any::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index 97982ecf..100a67f6 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -60,6 +60,8 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message {
// implements Any -----------------------------------------------
void PackFrom(const ::google::protobuf::Message& message);
+ void PackFrom(const ::google::protobuf::Message& message,
+ const ::std::string& type_url_prefix);
bool UnpackTo(::google::protobuf::Message* message) const;
template<typename T> bool Is() const {
return _any_metadata_.Is<T>();
@@ -182,6 +184,7 @@ inline ::std::string* Any::mutable_type_url() {
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Any::release_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -225,6 +228,7 @@ inline ::std::string* Any::mutable_value() {
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Any::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Any.value)
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index e8a18bc3..45db6ede 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -33,14 +33,43 @@ syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
option java_package = "com.google.protobuf";
option java_outer_classname = "AnyProto";
option java_multiple_files = true;
option java_generate_equals_and_hash = true;
option objc_class_prefix = "GPB";
-// `Any` contains an arbitrary serialized message along with a URL
-// that describes the type of the serialized message.
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
//
//
// JSON
@@ -73,7 +102,7 @@ option objc_class_prefix = "GPB";
//
message Any {
// A URL/resource name whose content describes the type of the
- // serialized message.
+ // serialized protocol buffer message.
//
// For URLs which use the schema `http`, `https`, or no schema, the
// following restrictions and interpretations apply:
@@ -81,6 +110,8 @@ message Any {
// * If no schema is provided, `https` is assumed.
// * The last segment of the URL's path must represent the fully
// qualified name of the type (as in `path/google.protobuf.Duration`).
+ // The name should be in a canonical form (e.g., leading "." is
+ // not accepted).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the
@@ -94,6 +125,6 @@ message Any {
//
string type_url = 1;
- // Must be valid serialized data of the above specified type.
+ // Must be a valid serialized protocol buffer of the above specified type.
bytes value = 2;
}
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index e589a89d..cbeba302 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -265,6 +265,7 @@ Api* Api::New(::google::protobuf::Arena* arena) const {
}
void Api::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
@@ -277,7 +278,7 @@ void Api::Clear() {
bool Api::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Api)
for (;;) {
@@ -538,6 +539,7 @@ void Api::SerializeWithCachedSizes(
}
int Api::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api)
int total_size = 0;
// optional string name = 1;
@@ -598,18 +600,22 @@ int Api::ByteSize() const {
}
void Api::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Api* source =
::google::protobuf::internal::DynamicCastToGenerated<const Api>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Api)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Api)
MergeFrom(*source);
}
}
void Api::MergeFrom(const Api& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
methods_.MergeFrom(from.methods_);
options_.MergeFrom(from.options_);
@@ -631,12 +637,14 @@ void Api::MergeFrom(const Api& from) {
}
void Api::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Api)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Api::CopyFrom(const Api& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Api)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -704,6 +712,7 @@ void Api::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Api::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -807,6 +816,7 @@ void Api::clear_version() {
return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Api::release_version() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -841,6 +851,7 @@ const ::google::protobuf::SourceContext& Api::source_context() const {
return source_context_;
}
::google::protobuf::SourceContext* Api::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -984,8 +995,17 @@ Method* Method::New(::google::protobuf::Arena* arena) const {
}
void Method::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(Method, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<Method*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -1005,7 +1025,7 @@ void Method::Clear() {
bool Method::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Method)
for (;;) {
@@ -1269,6 +1289,7 @@ void Method::SerializeWithCachedSizes(
}
int Method::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method)
int total_size = 0;
// optional string name = 1;
@@ -1323,18 +1344,22 @@ int Method::ByteSize() const {
}
void Method::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Method* source =
::google::protobuf::internal::DynamicCastToGenerated<const Method>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Method)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Method)
MergeFrom(*source);
}
}
void Method::MergeFrom(const Method& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
options_.MergeFrom(from.options_);
if (from.name().size() > 0) {
@@ -1361,12 +1386,14 @@ void Method::MergeFrom(const Method& from) {
}
void Method::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Method)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Method::CopyFrom(const Method& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Method)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1434,6 +1461,7 @@ void Method::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Method::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1477,6 +1505,7 @@ void Method::clear_request_type_url() {
return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Method::release_request_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1534,6 +1563,7 @@ void Method::clear_response_type_url() {
return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Method::release_response_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1678,13 +1708,14 @@ Mixin* Mixin::New(::google::protobuf::Arena* arena) const {
}
void Mixin::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
bool Mixin::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Mixin)
for (;;) {
@@ -1802,6 +1833,7 @@ void Mixin::SerializeWithCachedSizes(
}
int Mixin::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin)
int total_size = 0;
// optional string name = 1;
@@ -1825,18 +1857,22 @@ int Mixin::ByteSize() const {
}
void Mixin::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Mixin* source =
::google::protobuf::internal::DynamicCastToGenerated<const Mixin>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Mixin)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Mixin)
MergeFrom(*source);
}
}
void Mixin::MergeFrom(const Mixin& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.name().size() > 0) {
@@ -1849,12 +1885,14 @@ void Mixin::MergeFrom(const Mixin& from) {
}
void Mixin::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Mixin)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Mixin::CopyFrom(const Mixin& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Mixin)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1917,6 +1955,7 @@ void Mixin::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Mixin::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1960,6 +1999,7 @@ void Mixin::clear_root() {
return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Mixin::release_root() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index e1dca4e4..bb35e471 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -468,6 +468,7 @@ inline ::std::string* Api::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Api::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -571,6 +572,7 @@ inline ::std::string* Api::mutable_version() {
return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Api::release_version() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -605,6 +607,7 @@ inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
return source_context_;
}
inline ::google::protobuf::SourceContext* Api::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -699,6 +702,7 @@ inline ::std::string* Method::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Method::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -742,6 +746,7 @@ inline ::std::string* Method::mutable_request_type_url() {
return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Method::release_request_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -799,6 +804,7 @@ inline ::std::string* Method::mutable_response_type_url() {
return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Method::release_response_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -904,6 +910,7 @@ inline ::std::string* Mixin::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Mixin::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -947,6 +954,7 @@ inline ::std::string* Mixin::mutable_root() {
return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Mixin::release_root() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index cd0b21a7..613e5897 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/arena.h>
+
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
@@ -37,6 +38,7 @@
namespace google {
namespace protobuf {
+
google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
Arena::ThreadCache& Arena::thread_cache() {
@@ -247,6 +249,19 @@ uint64 Arena::SpaceUsed() const {
return space_used;
}
+pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
+ uint64 allocated = 0;
+ uint64 used = 0;
+
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ while (b != NULL) {
+ allocated += b->size;
+ used += (b->pos - kHeaderSize);
+ b = b->next;
+ }
+ return std::make_pair(allocated, used);
+}
+
uint64 Arena::FreeBlocks() {
uint64 space_allocated = 0;
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 5ad94fa9..b3d66d91 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -56,6 +56,7 @@ using type_info = ::type_info;
#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/type_traits.h>
+
namespace google {
namespace protobuf {
@@ -210,7 +211,12 @@ struct ArenaOptions {
//
// This protocol is implemented by all arena-enabled proto2 message classes as
// well as RepeatedPtrField.
+
+#if __cplusplus >= 201103L
+class Arena final {
+#else
class LIBPROTOBUF_EXPORT Arena {
+#endif
public:
// Arena constructor taking custom options. See ArenaOptions below for
// descriptions of the options available.
@@ -446,6 +452,10 @@ class LIBPROTOBUF_EXPORT Arena {
// As above, but does not include any free space in underlying blocks.
GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
+ // Combines SpaceAllocated and SpaceUsed. Returns a pair of
+ // <space_allocated, space_used>.
+ GOOGLE_ATTRIBUTE_NOINLINE pair<uint64, uint64> SpaceAllocatedAndUsed() const;
+
// Frees all storage allocated by this arena after calling destructors
// registered with OwnDestructor() and freeing objects registered with Own().
// Any objects allocated on this arena are unusable after this call. It also
@@ -507,11 +517,11 @@ class LIBPROTOBUF_EXPORT Arena {
//
// This is inside Arena because only Arena has the friend relationships
// necessary to see the underlying generated code traits.
- template<typename T>
- struct is_arena_constructable :
- public google::protobuf::internal::integral_constant<bool,
- sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
- const T>(static_cast<const T*>(0))) == sizeof(char)> {
+ template <typename T>
+ struct is_arena_constructable
+ : public google::protobuf::internal::integral_constant<
+ bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
+ const T>(static_cast<const T*>(0))) == sizeof(char)> {
};
private:
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
index 87a69b2a..56a7dd05 100644
--- a/src/google/protobuf/arena_nc_test.py
+++ b/src/google/protobuf/arena_nc_test.py
@@ -35,7 +35,7 @@
import unittest
from google3.testing.pybase import fake_target_util
-import unittest
+from google3.testing.pybase import unittest
class ArenaNcTest(unittest.TestCase):
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 6b67f446..ab25ffe1 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -342,6 +342,64 @@ TEST(ArenaTest, Swap) {
EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
}
+TEST(ArenaTest, ReflectionSwapFields) {
+ Arena arena1;
+ Arena arena2;
+ TestAllTypes* arena1_message;
+ TestAllTypes* arena2_message;
+
+ // Case 1: messages on different arenas, only one message is set.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena1_message);
+ const Reflection* reflection = arena1_message->GetReflection();
+ std::vector<const FieldDescriptor*> fields;
+ reflection->ListFields(*arena1_message, &fields);
+ reflection->SwapFields(arena1_message, arena2_message, fields);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+ string output;
+ arena1_message->SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+ TestUtil::ExpectAllFieldsSet(*arena2_message);
+ reflection->SwapFields(arena1_message, arena2_message, fields);
+ arena2_message->SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+ TestUtil::ExpectAllFieldsSet(*arena1_message);
+
+ // Case 2: messages on different arenas, both messages are set.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena1_message);
+ TestUtil::SetAllFields(arena2_message);
+ reflection->SwapFields(arena1_message, arena2_message, fields);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+ TestUtil::ExpectAllFieldsSet(*arena1_message);
+ TestUtil::ExpectAllFieldsSet(*arena2_message);
+
+ // Case 3: messages on different arenas with different lifetimes.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ {
+ Arena arena3;
+ TestAllTypes* arena3_message = Arena::CreateMessage<TestAllTypes>(&arena3);
+ TestUtil::SetAllFields(arena3_message);
+ reflection->SwapFields(arena1_message, arena3_message, fields);
+ }
+ TestUtil::ExpectAllFieldsSet(*arena1_message);
+
+ // Case 4: one message on arena, the other on heap.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ TestAllTypes message;
+ TestUtil::SetAllFields(arena1_message);
+ reflection->SwapFields(arena1_message, &message, fields);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(NULL, message.GetArena());
+ arena1_message->SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
TEST(ArenaTest, SetAllocatedMessage) {
Arena arena;
TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index e2e2f254..590ffce9 100755
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -134,7 +134,8 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
// UnsafeArenaRelease() on another field of a message in the same arena. Used
// to implement unsafe_arena_set_allocated_<field> in generated classes.
inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
- ::std::string* value, ::google::protobuf::Arena* /* arena */) {
+ ::std::string* value,
+ ::google::protobuf::Arena* /* arena */) {
if (value != NULL) {
ptr_ = value;
} else {
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index 3fb582be..ea405d7d 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -28,9 +28,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// arenastring_unittest.cc is not open-sourced. Do not include in open-source
-// distribution.
-
// Based on mvels@'s frankenstring.
#include <google/protobuf/arenastring.h>
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 3a816b05..fcad6b61 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -46,10 +46,11 @@
#include <unistd.h>
#endif
#include <errno.h>
+#include <fstream>
#include <iostream>
#include <ctype.h>
-#ifdef GOOGLE_PROTOBUF_ARCH_SPARC
+#ifdef GOOGLE_PROTOBUF_ARCH_SPARC
#include <limits.h> //For PATH_MAX
#endif
@@ -948,17 +949,23 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
return true;
}
+
CommandLineInterface::ParseArgumentStatus
CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
executable_name_ = argv[0];
+ vector<string> arguments;
+ for (int i = 1; i < argc; ++i) {
+ arguments.push_back(argv[i]);
+ }
+
// Iterate through all arguments and parse them.
- for (int i = 1; i < argc; i++) {
+ for (int i = 0; i < arguments.size(); ++i) {
string name, value;
- if (ParseArgument(argv[i], &name, &value)) {
+ if (ParseArgument(arguments[i].c_str(), &name, &value)) {
// Returned true => Use the next argument as the flag value.
- if (i + 1 == argc || argv[i+1][0] == '-') {
+ 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."
@@ -967,7 +974,7 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
return PARSE_ARGUMENT_FAIL;
} else {
++i;
- value = argv[i];
+ value = arguments[i];
}
}
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index f196ffc5..d1377666 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -212,6 +212,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Parse all command-line arguments.
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
+
// Parses a command-line argument into a name/value pair. Returns
// true if the next argument in the argv should be used as the value,
// false otherwise.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dda007d4..ae2900b1 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -60,16 +60,17 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-namespace google {
-namespace protobuf {
-namespace compiler {
// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
+namespace google {
+namespace protobuf {
+namespace compiler {
#if defined(_WIN32)
#ifndef STDIN_FILENO
@@ -376,7 +377,9 @@ void CommandLineInterfaceTest::CreateTempFile(
// Write file.
string full_name = temp_directory_ + "/" + name;
- GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true));
+ GOOGLE_CHECK_OK(File::SetContents(
+ full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
+ true));
}
void CommandLineInterfaceTest::CreateTempDir(const string& name) {
@@ -1090,6 +1093,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
}
#endif // !_WIN32
+
// -------------------------------------------------------------------
TEST_F(CommandLineInterfaceTest, ParseErrors) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 47729e1c..77451ab1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -54,6 +54,7 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 5ee6f000..c81c5982 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -69,11 +69,12 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
-void EnumGenerator::FillForwardDeclaration(set<string>* enum_names) {
+void EnumGenerator::FillForwardDeclaration(
+ map<string, const EnumDescriptor*>* enum_names) {
if (!options_.proto_h) {
return;
}
- enum_names->insert(classname_);
+ (*enum_names)[classname_] = descriptor_;
}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
@@ -83,6 +84,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
printer->Print(vars, "enum $enumbase$ {\n");
+ printer->Annotate("enumbase", descriptor_);
printer->Indent();
const EnumValueDescriptor* min_value = descriptor_->value(0);
@@ -96,9 +98,11 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
vars["number"] = Int32ToString(descriptor_->value(i)->number());
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
"" : classname_ + "_";
+ vars["deprecation"] = descriptor_->value(i)->options().deprecated() ?
+ " PROTOBUF_DEPRECATED" : "";
if (i > 0) printer->Print(",\n");
- printer->Print(vars, "$prefix$$name$ = $number$");
+ printer->Print(vars, "$prefix$$name$$deprecation$ = $number$");
if (descriptor_->value(i)->number() < min_value->number()) {
min_value = descriptor_->value(i);
@@ -140,15 +144,16 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
"$prefix$$short_name$_MAX + 1;\n\n");
}
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(vars,
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
// The _Name and _Parse methods
- printer->Print(vars,
- "inline const ::std::string& $classname$_Name($classname$ value) {\n"
- " return ::google::protobuf::internal::NameOfEnum(\n"
- " $classname$_descriptor(), value);\n"
- "}\n");
+ printer->Print(
+ vars,
+ "inline const ::std::string& $classname$_Name($classname$ value) {\n"
+ " return ::google::protobuf::internal::NameOfEnum(\n"
+ " $classname$_descriptor(), value);\n"
+ "}\n");
printer->Print(vars,
"inline bool $classname$_Parse(\n"
" const ::std::string& name, $classname$* value) {\n"
@@ -164,7 +169,7 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
"template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
"{};\n",
"classname", ClassName(descriptor_, true));
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
"template <>\n"
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
@@ -183,8 +188,11 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
for (int j = 0; j < descriptor_->value_count(); j++) {
vars["tag"] = EnumValueName(descriptor_->value(j));
+ vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
+ "PROTOBUF_DEPRECATED_ATTR " : "";
printer->Print(vars,
- "static $constexpr$const $nested_name$ $tag$ = $classname$_$tag$;\n");
+ "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n"
+ " $classname$_$tag$;\n");
}
printer->Print(vars,
@@ -201,16 +209,18 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
" $classname$_$nested_name$_ARRAYSIZE;\n");
}
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(vars,
"static inline const ::google::protobuf::EnumDescriptor*\n"
"$nested_name$_descriptor() {\n"
" return $classname$_descriptor();\n"
"}\n");
printer->Print(vars,
- "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
- " return $classname$_Name(value);\n"
- "}\n");
+ "static inline const ::std::string& "
+ "$nested_name$_Name($nested_name$ value) {"
+ "\n"
+ " return $classname$_Name(value);\n"
+ "}\n");
printer->Print(vars,
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
" $nested_name$* value) {\n"
@@ -240,7 +250,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
vars["classname"] = classname_;
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(vars,
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
" protobuf_AssignDescriptorsOnce();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index f3aa72e4..90edf001 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -35,12 +35,12 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+#include <map>
#include <set>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
-
namespace google {
namespace protobuf {
namespace io {
@@ -55,8 +55,7 @@ namespace cpp {
class EnumGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit EnumGenerator(const EnumDescriptor* descriptor,
- const Options& options);
+ EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
~EnumGenerator();
// Header stuff.
@@ -64,8 +63,10 @@ class EnumGenerator {
// Fills the name to use when declaring the enum. This is for use when
// generating other .proto.h files. This code should be placed within the
// enum's package namespace, but NOT within any class, even for nested
- // enums.
- void FillForwardDeclaration(set<string>* enum_names);
+ // enums. A given key in enum_names will map from an enum class name to the
+ // EnumDescriptor that was responsible for its inclusion in the map. This can
+ // be used to associate the descriptor with the code generated for it.
+ void FillForwardDeclaration(map<string, const EnumDescriptor*>* enum_names);
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
@@ -94,10 +95,10 @@ class EnumGenerator {
private:
const EnumDescriptor* descriptor_;
- string classname_;
- Options options_;
+ const string classname_;
+ const Options& options_;
// whether to generate the *_ARRAYSIZE constant.
- bool generate_array_size_;
+ const bool generate_array_size_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 824e2205..10252b39 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
namespace google {
namespace protobuf {
@@ -58,10 +59,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
// ===================================================================
-EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetEnumVariables(descriptor, &variables_, options);
}
@@ -75,8 +75,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "$type$ $name$() const$deprecation$;\n"
- "void set_$name$($type$ value)$deprecation$;\n");
+ "$deprecated_attr$$type$ $name$() const;\n"
+ "$deprecated_attr$void set_$name$($type$ value);\n");
}
void EnumFieldGenerator::
@@ -135,15 +135,16 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"if ($type$_IsValid(value)) {\n"
" set_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(variables_,
"} else {\n"
" mutable_unknown_fields()->AddVarint($number$, value);\n");
} else {
printer->Print(
"} else {\n"
- " unknown_fields_stream.WriteVarint32(tag);\n"
- " unknown_fields_stream.WriteVarint32(value);\n");
+ " unknown_fields_stream.WriteVarint32($tag$);\n"
+ " unknown_fields_stream.WriteVarint32(value);\n",
+ "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
}
printer->Print(variables_,
"}\n");
@@ -228,10 +229,9 @@ GenerateConstructorCode(io::Printer* printer) const {
// ===================================================================
-RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetEnumVariables(descriptor, &variables_, options);
}
@@ -241,8 +241,8 @@ void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField<int> $name$_;\n");
- if (descriptor_->is_packed()
- && HasGeneratedMethods(descriptor_->file())) {
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
@@ -251,12 +251,12 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "$type$ $name$(int index) const$deprecation$;\n"
- "void set_$name$(int index, $type$ value)$deprecation$;\n"
- "void add_$name$($type$ value)$deprecation$;\n");
+ "$deprecated_attr$$type$ $name$(int index) const;\n"
+ "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
+ "$deprecated_attr$void add_$name$($type$ value);\n");
printer->Print(variables_,
- "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
- "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
+ "$deprecated_attr$::google::protobuf::RepeatedField<int>* mutable_$name$();\n");
}
void RepeatedEnumFieldGenerator::
@@ -335,7 +335,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(variables_,
"} else {\n"
" mutable_unknown_fields()->AddVarint($number$, value);\n");
@@ -362,7 +362,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
" NULL,\n"
" NULL,\n"
" this->mutable_$name$())));\n");
- } else if (UseUnknownFieldSet(descriptor_->file())) {
+ } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
" input,\n"
@@ -399,7 +399,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
" } else {\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(variables_,
" mutable_unknown_fields()->AddVarint($number$, value);\n");
} else {
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 5b1d01ea..fe21c575 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -46,8 +46,7 @@ namespace cpp {
class EnumFieldGenerator : public FieldGenerator {
public:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -74,8 +73,8 @@ class EnumFieldGenerator : public FieldGenerator {
class EnumOneofFieldGenerator : public EnumFieldGenerator {
public:
- explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~EnumOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -91,8 +90,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator {
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 8d47d4e0..b3ba3a2e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -77,6 +77,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["deprecation"] = descriptor->options().deprecated()
? " PROTOBUF_DEPRECATED" : "";
+ (*variables)["deprecated_attr"] = descriptor->options().deprecated()
+ ? "PROTOBUF_DEPRECATED_ATTR " : "";
(*variables)["cppget"] = "Get";
@@ -121,6 +123,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
+ options_(options),
field_generators_(
new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 1d7f8233..3b012527 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -69,7 +69,7 @@ void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
class FieldGenerator {
public:
- FieldGenerator() {}
+ explicit FieldGenerator(const Options& options) : options_(options) {}
virtual ~FieldGenerator();
// Generate lines of code declaring members fields of the message class
@@ -194,6 +194,9 @@ class FieldGenerator {
// are placed in the message's ByteSize() method.
virtual void GenerateByteSize(io::Printer* printer) const = 0;
+ protected:
+ const Options& options_;
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
@@ -201,13 +204,14 @@ class FieldGenerator {
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
- explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+ FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
private:
const Descriptor* descriptor_;
+ const Options& options_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 37e4bae4..385b973e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -59,6 +59,7 @@ namespace cpp {
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
: file_(file),
+ options_(options),
message_generators_(
new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
enum_generators_(
@@ -66,8 +67,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
service_generators_(
new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_(
- new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
- options_(options) {
+ new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
@@ -94,7 +94,8 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
-void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
+void FileGenerator::GenerateProtoHeader(io::Printer* printer,
+ const string& info_path) {
if (!options_.proto_h) {
return;
}
@@ -114,6 +115,8 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
"dependency", dependency);
}
+ GenerateMetadataPragma(printer, info_path);
+
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -167,7 +170,8 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
GenerateBottomHeaderGuard(printer, filename_identifier);
}
-void FileGenerator::GeneratePBHeader(io::Printer* printer) {
+void FileGenerator::GeneratePBHeader(io::Printer* printer,
+ const string& info_path) {
string filename_identifier =
FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
GenerateTopHeaderGuard(printer, filename_identifier);
@@ -179,6 +183,7 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer) {
GenerateLibraryIncludes(printer);
}
GenerateDependencyIncludes(printer);
+ GenerateMetadataPragma(printer, info_path);
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -237,7 +242,7 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer) {
}
void FileGenerator::GenerateSource(io::Printer* printer) {
- bool well_known = IsWellKnownMessage(file_);
+ const bool use_system_include = IsWellKnownMessage(file_);
string header =
StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
printer->Print(
@@ -258,16 +263,16 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/wire_format_lite_inl.h>\n",
"filename", file_->name(),
"header", header,
- "left", well_known ? "<" : "\"",
- "right", well_known ? ">" : "\"");
+ "left", use_system_include ? "<" : "\"",
+ "right", use_system_include ? ">" : "\"");
// Unknown fields implementation in lite mode uses StringOutputStream
- if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
printer->Print(
"#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
}
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"#include <google/protobuf/descriptor.h>\n"
"#include <google/protobuf/generated_message_reflection.h>\n"
@@ -292,7 +297,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
GenerateNamespaceOpeners(printer);
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
"namespace {\n"
@@ -306,7 +311,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"name", ClassName(file_->enum_type(i), false));
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, options_)) {
for (int i = 0; i < file_->service_count(); i++) {
printer->Print(
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
@@ -331,7 +336,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// Generate classes.
for (int i = 0; i < file_->message_type_count(); i++) {
- if (i == 0 && HasGeneratedMethods(file_)) {
+ if (i == 0 && HasGeneratedMethods(file_, options_)) {
printer->Print(
"\n"
"namespace {\n"
@@ -356,7 +361,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, options_)) {
// Generate services.
for (int i = 0; i < file_->service_count(); i++) {
if (i == 0) printer->Print("\n");
@@ -401,20 +406,24 @@ class FileGenerator::ForwardDeclarations {
return ns;
}
- set<string>& classes() { return classes_; }
- set<string>& enums() { return enums_; }
+ map<string, const Descriptor*>& classes() { return classes_; }
+ map<string, const EnumDescriptor*>& enums() { return enums_; }
void Print(io::Printer* printer) const {
- for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
+ for (map<string, const EnumDescriptor *>::const_iterator
+ it = enums_.begin(),
+ end = enums_.end();
it != end; ++it) {
- printer->Print("enum $enumname$ : int;\n"
- "bool $enumname$_IsValid(int value);\n",
- "enumname", it->c_str());
+ printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
+ printer->Annotate("enumname", it->second);
+ printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
+ it->first);
}
- for (set<string>::const_iterator it = classes_.begin(),
- end = classes_.end();
+ for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
+ end = classes_.end();
it != end; ++it) {
- printer->Print("class $classname$;\n", "classname", it->c_str());
+ printer->Print("class $classname$;\n", "classname", it->first);
+ printer->Annotate("classname", it->second);
}
for (map<string, ForwardDeclarations *>::const_iterator
it = namespaces_.begin(),
@@ -431,8 +440,8 @@ class FileGenerator::ForwardDeclarations {
private:
map<string, ForwardDeclarations*> namespaces_;
- set<string> classes_;
- set<string> enums_;
+ map<string, const Descriptor*> classes_;
+ map<string, const EnumDescriptor*> enums_;
};
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
@@ -453,7 +462,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
// and we only use AddDescriptors() to allocate default instances.
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
"void $assigndescriptorsname$() {\n",
@@ -486,7 +495,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_->enum_type_count(); i++) {
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, options_)) {
for (int i = 0; i < file_->service_count(); i++) {
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
@@ -552,22 +561,23 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// Now generate the AddDescriptors() function.
PrintHandlingOptionalStaticInitializers(
- file_, printer,
- // With static initializers.
- // Note that we don't need any special synchronization in the following code
- // because it is called at static init time before any threads exist.
- "void $adddescriptorsname$() {\n"
- " static bool already_here = false;\n"
- " if (already_here) return;\n"
- " already_here = true;\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
- "\n",
- // Without.
- "void $adddescriptorsname$_impl() {\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
- "\n",
- // Vars.
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+ file_, options_, printer,
+ // With static initializers.
+ // Note that we don't need any special synchronization in the following
+ // code
+ // because it is called at static init time before any threads exist.
+ "void $adddescriptorsname$() {\n"
+ " static bool already_here = false;\n"
+ " if (already_here) return;\n"
+ " already_here = true;\n"
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
+ // Without.
+ "void $adddescriptorsname$_impl() {\n"
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
+ // Vars.
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
printer->Indent();
@@ -584,7 +594,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"name", add_desc_name);
}
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
// 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.
@@ -678,23 +688,23 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"\n");
PrintHandlingOptionalStaticInitializers(
- file_, printer,
- // With static initializers.
- "// Force AddDescriptors() to be called at static initialization time.\n"
- "struct StaticDescriptorInitializer_$filename$ {\n"
- " StaticDescriptorInitializer_$filename$() {\n"
- " $adddescriptorsname$();\n"
- " }\n"
- "} static_descriptor_initializer_$filename$_;\n",
- // Without.
- "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
- "void $adddescriptorsname$() {\n"
- " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
- " &$adddescriptorsname$_impl);\n"
- "}\n",
- // Vars.
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "filename", FilenameIdentifier(file_->name()));
+ file_, options_, printer,
+ // With static initializers.
+ "// Force AddDescriptors() to be called at static initialization time.\n"
+ "struct StaticDescriptorInitializer_$filename$ {\n"
+ " StaticDescriptorInitializer_$filename$() {\n"
+ " $adddescriptorsname$();\n"
+ " }\n"
+ "} static_descriptor_initializer_$filename$_;\n",
+ // Without.
+ "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
+ "void $adddescriptorsname$() {\n"
+ " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
+ " &$adddescriptorsname$_impl);\n"
+ "}\n",
+ // Vars.
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
+ FilenameIdentifier(file_->name()));
}
void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
@@ -751,16 +761,15 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
const string& filename_identifier) {
// Generate top of header.
printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n"
- "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
- "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
- "\n"
- "#include <string>\n"
- "\n",
- "filename", file_->name(),
- "filename_identifier", filename_identifier);
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "\n"
+ "#include <string>\n",
+ "filename", file_->name(), "filename_identifier", filename_identifier);
+ printer->Print("\n");
}
void FileGenerator::GenerateBottomHeaderGuard(
@@ -799,12 +808,12 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
"#include <google/protobuf/arena.h>\n"
"#include <google/protobuf/arenastring.h>\n"
"#include <google/protobuf/generated_message_util.h>\n");
- if (UseUnknownFieldSet(file_)) {
+ if (UseUnknownFieldSet(file_, options_)) {
printer->Print(
"#include <google/protobuf/metadata.h>\n");
}
if (file_->message_type_count() > 0) {
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"#include <google/protobuf/message.h>\n");
} else {
@@ -818,7 +827,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
if (HasMapFields(file_)) {
printer->Print(
"#include <google/protobuf/map.h>\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"#include <google/protobuf/map_field_inl.h>\n");
} else {
@@ -828,7 +837,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
}
if (HasEnumDefinitions(file_)) {
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"#include <google/protobuf/generated_enum_reflection.h>\n");
} else {
@@ -837,12 +846,12 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
}
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, options_)) {
printer->Print(
"#include <google/protobuf/service.h>\n");
}
- if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
printer->Print(
"#include <google/protobuf/unknown_field_set.h>\n");
}
@@ -854,6 +863,19 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
}
}
+void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
+ const string& info_path) {
+ if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
+ !options_.annotation_guard_name.empty()) {
+ printer->Print(
+ "#ifdef $guard$\n"
+ "#pragma $pragma$ \"$info_path$\"\n"
+ "#endif // $guard$\n",
+ "guard", options_.annotation_guard_name, "pragma",
+ options_.annotation_pragma_name, "info_path", info_path);
+ }
+}
+
void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
set<string> public_import_names;
for (int i = 0; i < file_->public_dependency_count(); i++) {
@@ -861,16 +883,17 @@ void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
}
for (int i = 0; i < file_->dependency_count(); i++) {
- bool well_known = IsWellKnownMessage(file_->dependency(i));
+ const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
const string& name = file_->dependency(i)->name();
bool public_import = (public_import_names.count(name) != 0);
+
printer->Print(
"#include $left$$dependency$.pb.h$right$$iwyu$\n",
"dependency", StripProto(name),
"iwyu", (public_import) ? " // IWYU pragma: export" : "",
- "left", well_known ? "<" : "\"",
- "right", well_known ? ">" : "\"");
+ "left", use_system_include ? "<" : "\"",
+ "right", use_system_include ? ">" : "\"");
}
}
@@ -897,13 +920,15 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
}
void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
- set<string> classes;
+ map<string, const Descriptor*> classes;
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->FillMessageForwardDeclarations(&classes);
}
- for (set<string>::const_iterator it = classes.begin(), end = classes.end();
+ for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
+ end = classes.end();
it != end; ++it) {
- printer->Print("class $classname$;\n", "classname", it->c_str());
+ printer->Print("class $classname$;\n", "classname", it->first);
+ printer->Annotate("classname", it->second);
}
}
@@ -930,7 +955,7 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
}
void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, options_)) {
// Generate service definitions.
for (int i = 0; i < file_->service_count(); i++) {
if (i > 0) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 29cdaea5..5dcf692b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -65,12 +65,17 @@ class ExtensionGenerator; // extension.h
class FileGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit FileGenerator(const FileDescriptor* file,
- const Options& options);
+ FileGenerator(const FileDescriptor* file, const Options& options);
~FileGenerator();
- void GenerateProtoHeader(io::Printer* printer);
- void GeneratePBHeader(io::Printer* printer);
+ // info_path, if non-empty, should be the path (relative to printer's output)
+ // to the metadata file describing this proto header.
+ void GenerateProtoHeader(io::Printer* printer,
+ const string& info_path);
+ // info_path, if non-empty, should be the path (relative to printer's output)
+ // to the metadata file describing this PB header.
+ void GeneratePBHeader(io::Printer* printer,
+ const string& info_path);
void GenerateSource(io::Printer* printer);
private:
@@ -102,6 +107,10 @@ class FileGenerator {
void GenerateLibraryIncludes(io::Printer* printer);
void GenerateDependencyIncludes(io::Printer* printer);
+ // Generate a pragma to pull in metadata using the given info_path (if
+ // non-empty). info_path should be relative to printer's output.
+ void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
+
// Generates a couple of different pieces before definitions:
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
@@ -134,6 +143,7 @@ class FileGenerator {
void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
const FileDescriptor* file_;
+ const Options options_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
@@ -142,7 +152,6 @@ class FileGenerator {
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
vector<string> package_parts_;
- const Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 781526b5..31d189c2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -90,6 +90,14 @@ bool CppGenerator::Generate(const FileDescriptor* file,
file_options.dllexport_decl = options[i].second;
} else if (options[i].first == "safe_boundary_check") {
file_options.safe_boundary_check = true;
+ } else if (options[i].first == "annotate_headers") {
+ file_options.annotate_headers = true;
+ } else if (options[i].first == "annotation_pragma_name") {
+ file_options.annotation_pragma_name = options[i].second;
+ } else if (options[i].first == "annotation_guard_name") {
+ file_options.annotation_guard_name = options[i].second;
+ } else if (options[i].first == "lite") {
+ file_options.enforce_lite = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@@ -107,16 +115,40 @@ bool CppGenerator::Generate(const FileDescriptor* file,
if (file_options.proto_h) {
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".proto.h"));
- io::Printer printer(output.get(), '$');
- file_generator.GenerateProtoHeader(&printer);
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ string info_path = basename + ".proto.h.meta";
+ io::Printer printer(output.get(), '$', file_options.annotate_headers
+ ? &annotation_collector
+ : NULL);
+ file_generator.GenerateProtoHeader(
+ &printer, file_options.annotate_headers ? info_path : "");
+ if (file_options.annotate_headers) {
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
+ generator_context->Open(info_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
}
basename.append(".pb");
{
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".h"));
- io::Printer printer(output.get(), '$');
- file_generator.GeneratePBHeader(&printer);
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ string info_path = basename + ".h.meta";
+ io::Printer printer(output.get(), '$', file_options.annotate_headers
+ ? &annotation_collector
+ : NULL);
+ file_generator.GeneratePBHeader(
+ &printer, file_options.annotate_headers ? info_path : "");
+ if (file_options.annotate_headers) {
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
+ generator_context->Open(info_path));
+ annotations.SerializeToZeroCopyStream(info_output.get());
+ }
}
// Generate cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index fb46e387..2ad4d36a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -68,14 +68,15 @@ const char* const kKeywordList[] = {
"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", "extern", "false",
- "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
- "namespace", "new", "noexcept", "not", "not_eq", "NULL", "operator", "or",
- "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
- "return", "short", "signed", "sizeof", "static", "static_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"
+ "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
+ "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
+ "mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL",
+ "operator", "or", "or_eq", "private", "protected", "public", "register",
+ "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
+ "static_assert", "static_cast", "struct", "switch", "template", "this",
+ "thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
+ "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
+ "while", "xor", "xor_eq"
};
hash_set<string> MakeKeywordsMap() {
@@ -171,9 +172,10 @@ string DependentBaseClassTemplateName(const Descriptor* descriptor) {
return ClassName(descriptor, false) + "_InternalBase";
}
-string SuperClassName(const Descriptor* descriptor) {
- return HasDescriptorMethods(descriptor->file()) ?
- "::google::protobuf::Message" : "::google::protobuf::MessageLite";
+string SuperClassName(const Descriptor* descriptor, const Options& options) {
+ return HasDescriptorMethods(descriptor->file(), options)
+ ? "::google::protobuf::Message"
+ : "::google::protobuf::MessageLite";
}
string DependentBaseDownCast() {
@@ -485,8 +487,9 @@ string SafeFunctionName(const Descriptor* descriptor,
return function_name;
}
-bool StaticInitializersForced(const FileDescriptor* file) {
- if (HasDescriptorMethods(file) || file->extension_count() > 0) {
+bool StaticInitializersForced(const FileDescriptor* file,
+ const Options& options) {
+ if (HasDescriptorMethods(file, options) || file->extension_count() > 0) {
return true;
}
for (int i = 0; i < file->message_type_count(); ++i) {
@@ -498,10 +501,10 @@ bool StaticInitializersForced(const FileDescriptor* file) {
}
void PrintHandlingOptionalStaticInitializers(
- const FileDescriptor* file, io::Printer* printer,
+ const FileDescriptor* file, const Options& options, io::Printer* printer,
const char* with_static_init, const char* without_static_init,
- const char* var1, const string& val1,
- const char* var2, const string& val2) {
+ const char* var1, const string& val1, const char* var2,
+ const string& val2) {
map<string, string> vars;
if (var1) {
vars[var1] = val1;
@@ -510,14 +513,16 @@ void PrintHandlingOptionalStaticInitializers(
vars[var2] = val2;
}
PrintHandlingOptionalStaticInitializers(
- vars, file, printer, with_static_init, without_static_init);
+ vars, file, options, printer, with_static_init, without_static_init);
}
-void PrintHandlingOptionalStaticInitializers(
- const map<string, string>& vars, const FileDescriptor* file,
- io::Printer* printer, const char* with_static_init,
- const char* without_static_init) {
- if (StaticInitializersForced(file)) {
+void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
+ const FileDescriptor* file,
+ const Options& options,
+ io::Printer* printer,
+ const char* with_static_init,
+ const char* without_static_init) {
+ if (StaticInitializersForced(file, options)) {
printer->Print(vars, with_static_init);
} else {
printer->Print(vars, (string(
@@ -612,10 +617,11 @@ enum Utf8CheckMode {
};
// Which level of UTF-8 enforcemant is placed on this file.
-static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
+static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+ const Options& options) {
if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
return STRICT;
- } else if (field->file()->options().optimize_for() !=
+ } else if (GetOptimizeFor(field->file(), options) !=
FileOptions::LITE_RUNTIME) {
return VERIFY;
} else {
@@ -624,13 +630,13 @@ static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
}
static void GenerateUtf8CheckCode(const FieldDescriptor* field,
- bool for_parse,
+ const Options& options, bool for_parse,
const map<string, string>& variables,
const char* parameters,
const char* strict_function,
const char* verify_function,
io::Printer* printer) {
- switch (GetUtf8CheckMode(field)) {
+ switch (GetUtf8CheckMode(field, options)) {
case STRICT: {
if (for_parse) {
printer->Print("DO_(");
@@ -674,23 +680,22 @@ static void GenerateUtf8CheckCode(const FieldDescriptor* field,
}
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
- bool for_parse,
+ const Options& options, bool for_parse,
const map<string, string>& variables,
const char* parameters,
io::Printer* printer) {
- GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+ GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
"VerifyUtf8String", "VerifyUTF8StringNamedField",
printer);
}
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
- bool for_parse,
+ const Options& options, bool for_parse,
const map<string, string>& variables,
const char* parameters,
io::Printer* printer) {
- GenerateUtf8CheckCode(field, for_parse, variables, parameters,
- "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
- printer);
+ GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
+ "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index a22d414d..018acfca 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -37,8 +37,9 @@
#include <map>
#include <string>
-#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
@@ -72,7 +73,7 @@ string DependentBaseClassTemplateName(const Descriptor* descriptor);
// Name of the base class: either the dependent base class (for use with
// proto_h) or google::protobuf::Message.
-string SuperClassName(const Descriptor* descriptor);
+string SuperClassName(const Descriptor* descriptor, const Options& options);
// Returns a string that down-casts from the dependent base class to the
// derived class.
@@ -118,7 +119,7 @@ string DependentTypeName(const FieldDescriptor* field);
string FieldMessageTypeName(const FieldDescriptor* field);
// Strips ".proto" or ".protodevel" from the end of a filename.
-string StripProto(const string& filename);
+LIBPROTOC_EXPORT string StripProto(const string& filename);
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
// Note: non-built-in type names will be qualified, meaning they will start
@@ -168,12 +169,17 @@ inline bool PreserveUnknownFields(const Descriptor* message) {
return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
+// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
+::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+ const FileDescriptor* file, const Options& options);
+
// If PreserveUnknownFields() is true, determines whether unknown
// fields will be stored in an UnknownFieldSet or a string.
// If PreserveUnknownFields() is false, this method will not be
// used.
-inline bool UseUnknownFieldSet(const FileDescriptor* file) {
- return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+inline bool UseUnknownFieldSet(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
}
@@ -186,45 +192,52 @@ bool HasEnumDefinitions(const FileDescriptor* file);
// Does this file have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor* file) {
- return file->options().optimize_for() != FileOptions::CODE_SIZE;
+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) {
- return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+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) {
+inline bool HasGenericServices(const FileDescriptor* file,
+ const Options& options) {
return file->service_count() > 0 &&
- file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
file->options().cc_generic_services();
}
// Should we generate a separate, super-optimized code path for serializing to
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
// size.
-inline bool HasFastArraySerialization(const FileDescriptor* file) {
- return file->options().optimize_for() == FileOptions::SPEED;
+inline bool HasFastArraySerialization(const FileDescriptor* file,
+ const Options& options) {
+ return GetOptimizeFor(file, options) == FileOptions::SPEED;
}
// Returns whether we have to generate code with static initializers.
-bool StaticInitializersForced(const FileDescriptor* file);
+bool StaticInitializersForced(const FileDescriptor* file,
+ const Options& options);
// Prints 'with_static_init' if static initializers have to be used for the
// provided file. Otherwise emits both 'with_static_init' and
// 'without_static_init' using #ifdef.
void PrintHandlingOptionalStaticInitializers(
- const FileDescriptor* file, io::Printer* printer,
+ const FileDescriptor* file, const Options& options, io::Printer* printer,
const char* with_static_init, const char* without_static_init,
- const char* var1 = NULL, const string& val1 = "",
- const char* var2 = NULL, const string& val2 = "");
+ const char* var1 = NULL, const string& val1 = "", const char* var2 = NULL,
+ const string& val2 = "");
-void PrintHandlingOptionalStaticInitializers(
- const map<string, string>& vars, const FileDescriptor* file,
- io::Printer* printer, const char* with_static_init,
- const char* without_static_init);
+void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
+ const FileDescriptor* file,
+ const Options& options,
+ io::Printer* printer,
+ const char* with_static_init,
+ const char* without_static_init);
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
@@ -267,19 +280,23 @@ bool IsAnyMessage(const Descriptor* descriptor);
bool IsWellKnownMessage(const FileDescriptor* descriptor);
-void GenerateUtf8CheckCodeForString(
- const FieldDescriptor* field,
- bool for_parse,
- const map<string, string>& variables,
- const char* parameters,
- io::Printer* printer);
-
-void GenerateUtf8CheckCodeForCord(
- const FieldDescriptor* field,
- bool for_parse,
- const map<string, string>& variables,
- const char* parameters,
- io::Printer* printer);
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer);
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ const Options& options, bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters, io::Printer* printer);
+
+inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+ const FileDescriptor* file, const Options& options) {
+ return options.enforce_lite
+ ? FileOptions::LITE_RUNTIME
+ : file->options().optimize_for();
+}
} // namespace cpp
} // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index e5e2f07d..f585c31b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -49,10 +49,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
- (*variables)["stream_writer"] = (*variables)["declared_type"] +
- (HasFastArraySerialization(descriptor->message_type()->file()) ?
- "MaybeToArray" :
- "");
+ (*variables)["stream_writer"] =
+ (*variables)["declared_type"] +
+ (HasFastArraySerialization(descriptor->message_type()->file(), options)
+ ? "MaybeToArray"
+ : "");
(*variables)["full_name"] = descriptor->full_name();
const FieldDescriptor* key =
@@ -83,7 +84,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
- if (HasDescriptorMethods(descriptor->file())) {
+ if (HasDescriptorMethods(descriptor->file(), options)) {
(*variables)["lite"] = "";
} else {
(*variables)["lite"] = "Lite";
@@ -98,10 +99,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
}
}
-MapFieldGenerator::
-MapFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor),
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(options),
+ descriptor_(descriptor),
dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -127,10 +128,10 @@ GeneratePrivateMembers(io::Printer* printer) const {
void MapFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
- " $name$() const$deprecation$;\n"
- "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
- " mutable_$name$()$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+ " $name$() const;\n"
+ "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+ " mutable_$name$();\n");
}
void MapFieldGenerator::
@@ -170,7 +171,7 @@ GenerateSwappingCode(io::Printer* printer) const {
void MapFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(variables_,
"$name$_.SetAssignDescriptorCallback(\n"
" protobuf_AssignDescriptorsOnce);\n"
@@ -217,7 +218,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" (*mutable_$name$())[entry->key()] =\n"
" static_cast< $val_cpp$ >(*entry->mutable_value());\n"
" } else {\n");
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(variables_,
" mutable_unknown_fields()"
"->AddLengthDelimited($number$, data);\n");
@@ -238,14 +239,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
descriptor_->message_type()->FindFieldByName("key");
if (key_field->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- key_field, true, variables_,
+ key_field, options_, true, variables_,
"entry->key().data(), entry->key().length(),\n", printer);
}
if (value_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(
- value_field, true, variables_,
- "entry->mutable_value()->data(),\n"
- "entry->mutable_value()->length(),\n", printer);
+ GenerateUtf8CheckCodeForString(value_field, options_, true, variables_,
+ "entry->mutable_value()->data(),\n"
+ "entry->mutable_value()->length(),\n",
+ printer);
}
// If entry is allocated by arena, its desctructor should be avoided.
@@ -285,14 +286,14 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
const FieldDescriptor* value_field =
descriptor_->message_type()->FindFieldByName("value");
if (key_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(
- key_field, false, variables_,
- "it->first.data(), it->first.length(),\n", printer);
+ GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
+ "it->first.data(), it->first.length(),\n",
+ printer);
}
if (value_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(
- value_field, false, variables_,
- "it->second.data(), it->second.length(),\n", printer);
+ GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
+ "it->second.data(), it->second.length(),\n",
+ printer);
}
printer->Outdent();
@@ -343,14 +344,14 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
const FieldDescriptor* value_field =
descriptor_->message_type()->FindFieldByName("value");
if (key_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(
- key_field, false, variables_,
- "it->first.data(), it->first.length(),\n", printer);
+ GenerateUtf8CheckCodeForString(key_field, options_, false, variables_,
+ "it->first.data(), it->first.length(),\n",
+ printer);
}
if (value_field->type() == FieldDescriptor::TYPE_STRING) {
- GenerateUtf8CheckCodeForString(
- value_field, false, variables_,
- "it->second.data(), it->second.length(),\n", printer);
+ GenerateUtf8CheckCodeForString(value_field, options_, false, variables_,
+ "it->second.data(), it->second.length(),\n",
+ printer);
}
printer->Outdent();
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 5e205623..087dcde0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -43,8 +43,7 @@ namespace cpp {
class MapFieldGenerator : public FieldGenerator {
public:
- explicit MapFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
~MapFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 8304ebbd..da2a4c92 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -106,8 +106,8 @@ struct ExtensionRangeSorter {
// Returns true if the "required" restriction check should be ignored for the
// given field.
-inline static bool ShouldIgnoreRequiredFieldCheck(
- const FieldDescriptor* field) {
+inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
+ const Options& options) {
return false;
}
@@ -116,9 +116,8 @@ inline static bool ShouldIgnoreRequiredFieldCheck(
//
// already_seen is used to avoid checking the same type multiple times
// (and also to protect against recursion).
-static bool HasRequiredFields(
- const Descriptor* type,
- hash_set<const Descriptor*>* already_seen) {
+static bool HasRequiredFields(const Descriptor* type, const Options& options,
+ hash_set<const Descriptor*>* already_seen) {
if (already_seen->count(type) > 0) {
// Since the first occurrence of a required field causes the whole
// function to return true, we can assume that if the type is already
@@ -138,8 +137,8 @@ static bool HasRequiredFields(
return true;
}
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
- !ShouldIgnoreRequiredFieldCheck(field)) {
- if (HasRequiredFields(field->message_type(), already_seen)) {
+ !ShouldIgnoreRequiredFieldCheck(field, options)) {
+ if (HasRequiredFields(field->message_type(), options, already_seen)) {
return true;
}
}
@@ -148,9 +147,9 @@ static bool HasRequiredFields(
return false;
}
-static bool HasRequiredFields(const Descriptor* type) {
+static bool HasRequiredFields(const Descriptor* type, const Options& options) {
hash_set<const Descriptor*> already_seen;
- return HasRequiredFields(type, &already_seen);
+ return HasRequiredFields(type, options, &already_seen);
}
// This returns an estimate of the compiler's alignment for the field. This
@@ -423,8 +422,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::
-FillMessageForwardDeclarations(set<string>* class_names) {
- class_names->insert(classname_);
+FillMessageForwardDeclarations(map<string, const Descriptor*>* class_names) {
+ (*class_names)[classname_] = descriptor_;
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need forward declaration. Since map entry
@@ -436,7 +435,7 @@ FillMessageForwardDeclarations(set<string>* class_names) {
}
void MessageGenerator::
-FillEnumForwardDeclarations(set<string>* enum_names) {
+FillEnumForwardDeclarations(map<string, const EnumDescriptor*>* enum_names) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
}
@@ -480,7 +479,7 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
// If the message is dependent, the inline clear_*() method will need
// to delete the message type, so it must be in the dependent base
// class. (See also GenerateFieldAccessorDeclarations.)
- printer->Print(vars, "void clear_$name$()$deprecation$;\n");
+ printer->Print(vars, "$deprecated_attr$void clear_$name$();\n");
}
// Generate type-specific accessor declarations.
field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
@@ -515,22 +514,24 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
}
if (field->is_repeated()) {
- printer->Print(vars, "int $name$_size() const$deprecation$;\n");
+ printer->Print(vars, "$deprecated_attr$int $name$_size() const;\n");
} else if (HasHasMethod(field)) {
- printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
+ printer->Print(vars, "$deprecated_attr$bool has_$name$() const;\n");
} else if (HasPrivateHasMethod(field)) {
printer->Print(vars,
"private:\n"
- "bool has_$name$() const$deprecation$;\n"
+ "bool has_$name$() const;\n"
"public:\n");
}
if (!dependent_field) {
// If this field is dependent, then its clear_() method is in the
// depenent base class. (See also GenerateDependentAccessorDeclarations.)
- printer->Print(vars, "void clear_$name$()$deprecation$;\n");
+ printer->Print(vars, "$deprecated_attr$void clear_$name$();\n");
}
- printer->Print(vars, "static const int $constant_name$ = $number$;\n");
+ printer->Print(vars,
+ "$deprecated_attr$static const int $constant_name$ = "
+ "$number$;\n");
// Generate type-specific accessor declarations.
field_generators_.get(field).GenerateAccessorDeclarations(printer);
@@ -837,7 +838,7 @@ GenerateDependentBaseClassDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = DependentBaseClassTemplateName(descriptor_);
- vars["superclass"] = SuperClassName(descriptor_);
+ vars["superclass"] = SuperClassName(descriptor_, options_);
printer->Print(vars,
"template <class T>\n"
@@ -888,10 +889,11 @@ GenerateClassDefinition(io::Printer* printer) {
vars["superclass"] =
DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
} else {
- vars["superclass"] = SuperClassName(descriptor_);
+ vars["superclass"] = SuperClassName(descriptor_, options_);
}
printer->Print(vars,
"class $dllexport$$classname$ : public $superclass$ {\n");
+ printer->Annotate("classname", descriptor_);
if (use_dependent_base_) {
printer->Print(vars, " friend class $superclass$;\n");
}
@@ -911,7 +913,7 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
" return _internal_metadata_.unknown_fields();\n"
@@ -965,7 +967,7 @@ GenerateClassDefinition(io::Printer* printer) {
}
// Only generate this member if it's not disabled.
- if (HasDescriptorMethods(descriptor_->file()) &&
+ if (HasDescriptorMethods(descriptor_->file(), options_) &&
!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(vars,
"static const ::google::protobuf::Descriptor* descriptor();\n");
@@ -1002,7 +1004,7 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- if (!StaticInitializersForced(descriptor_->file())) {
+ if (!StaticInitializersForced(descriptor_->file(), options_)) {
printer->Print(vars,
"#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
"// Returns the internal default instance pointer. This function can\n"
@@ -1027,6 +1029,8 @@ GenerateClassDefinition(io::Printer* printer) {
"// implements Any -----------------------------------------------\n"
"\n"
"void PackFrom(const ::google::protobuf::Message& message);\n"
+ "void PackFrom(const ::google::protobuf::Message& message,\n"
+ " const ::std::string& type_url_prefix);\n"
"bool UnpackTo(::google::protobuf::Message* message) const;\n"
"template<typename T> bool Is() const {\n"
" return _any_metadata_.Is<T>();\n"
@@ -1043,8 +1047,8 @@ GenerateClassDefinition(io::Printer* printer) {
"\n"
"$classname$* New(::google::protobuf::Arena* arena) const;\n");
- if (HasGeneratedMethods(descriptor_->file())) {
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(vars,
"void CopyFrom(const ::google::protobuf::Message& from);\n"
"void MergeFrom(const ::google::protobuf::Message& from);\n");
@@ -1066,11 +1070,11 @@ GenerateClassDefinition(io::Printer* printer) {
" ::google::protobuf::io::CodedOutputStream* output) const;\n");
// DiscardUnknownFields() is implemented in message.cc using reflections. We
// need to implement this function in generated code for messages.
- if (!UseUnknownFieldSet(descriptor_->file())) {
+ if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"void DiscardUnknownFields();\n");
}
- if (HasFastArraySerialization(descriptor_->file())) {
+ if (HasFastArraySerialization(descriptor_->file(), options_)) {
printer->Print(
"::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
}
@@ -1093,7 +1097,7 @@ GenerateClassDefinition(io::Printer* printer) {
}
uses_string_ = false;
if (PreserveUnknownFields(descriptor_) &&
- !UseUnknownFieldSet(descriptor_->file())) {
+ !UseUnknownFieldSet(descriptor_->file(), options_)) {
uses_string_ = true;
}
for (int i = 0; i < descriptors.size(); i++) {
@@ -1123,7 +1127,7 @@ GenerateClassDefinition(io::Printer* printer) {
"classname", classname_);
}
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"private:\n"
"inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
@@ -1147,7 +1151,7 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
"::google::protobuf::Metadata GetMetadata() const;\n"
"\n");
@@ -1236,7 +1240,7 @@ GenerateClassDefinition(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
- if (HasGeneratedMethods(descriptor_->file()) &&
+ if (HasGeneratedMethods(descriptor_->file(), options_) &&
!descriptor_->options().message_set_wire_format() &&
num_required_fields_ > 1) {
printer->Print(
@@ -1278,7 +1282,7 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
} else {
@@ -1405,15 +1409,14 @@ GenerateClassDefinition(io::Printer* printer) {
// friends so that they can access private static variables like
// default_instance_ and reflection_.
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- "friend void $dllexport_decl$ $adddescriptorsname$();\n",
- // Without.
- "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
- // Vars.
- "dllexport_decl", options_.dllexport_decl,
- "adddescriptorsname",
- GlobalAddDescriptorsName(descriptor_->file()->name()));
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ "friend void $dllexport_decl$ $adddescriptorsname$();\n",
+ // Without.
+ "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
+ // Vars.
+ "dllexport_decl", options_.dllexport_decl, "adddescriptorsname",
+ GlobalAddDescriptorsName(descriptor_->file()->name()));
printer->Print(
"friend void $assigndescriptorsname$();\n"
@@ -1576,7 +1579,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
// Unknown field offset: either points to the unknown field set if embedded
// directly, or indicates that the unknown field set is stored as part of the
// internal metadata if not.
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(vars,
" -1,\n");
} else {
@@ -1616,7 +1619,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
// arena pointer and unknown field set (in a space-efficient way) if we use
// that implementation strategy, or an offset directly to the arena pointer if
// not (because e.g. we don't have an unknown field set).
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
"$classname$, _internal_metadata_),\n");
@@ -1706,7 +1709,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
"classname", classname_);
if ((descriptor_->oneof_decl_count() > 0) &&
- HasDescriptorMethods(descriptor_->file())) {
+ HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
"$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
"classname", classname_);
@@ -1746,7 +1749,7 @@ GenerateShutdownCode(io::Printer* printer) {
"delete $classname$::default_instance_;\n",
"classname", classname_);
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
if (descriptor_->oneof_decl_count() > 0) {
printer->Print(
"delete $classname$_default_oneof_instance_;\n",
@@ -1774,7 +1777,8 @@ void MessageGenerator::
GenerateClassMethods(io::Printer* printer) {
// mutable_unknown_fields wrapper function for LazyStringOutputStream
// callback.
- if (!UseUnknownFieldSet(descriptor_->file())) {
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"static ::std::string* MutableUnknownFieldsFor$classname$(\n"
" $classname$* ptr) {\n"
@@ -1789,6 +1793,11 @@ GenerateClassMethods(io::Printer* printer) {
" _any_metadata_.PackFrom(message);\n"
"}\n"
"\n"
+ "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n"
+ " const ::std::string& type_url_prefix) {\n"
+ " _any_metadata_.PackFrom(message, type_url_prefix);\n"
+ "}\n"
+ "\n"
"bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
" return _any_metadata_.UnpackTo(message);\n"
"}\n"
@@ -1843,7 +1852,7 @@ GenerateClassMethods(io::Printer* printer) {
printer->Print("\n");
}
- if (HasGeneratedMethods(descriptor_->file())) {
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
GenerateClear(printer);
printer->Print("\n");
@@ -1853,7 +1862,7 @@ GenerateClassMethods(io::Printer* printer) {
GenerateSerializeWithCachedSizes(printer);
printer->Print("\n");
- if (HasFastArraySerialization(descriptor_->file())) {
+ if (HasFastArraySerialization(descriptor_->file(), options_)) {
GenerateSerializeWithCachedSizesToArray(printer);
printer->Print("\n");
}
@@ -1874,7 +1883,7 @@ GenerateClassMethods(io::Printer* printer) {
GenerateSwap(printer);
printer->Print("\n");
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(
"::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
" protobuf_AssignDescriptorsOnce();\n"
@@ -1899,11 +1908,10 @@ GenerateClassMethods(io::Printer* printer) {
void MessageGenerator::
GenerateOffsets(io::Printer* printer) {
- printer->Print(
- "static const int $classname$_offsets_[$field_count$] = {\n",
- "classname", classname_,
- "field_count", SimpleItoa(max(
- 1, descriptor_->field_count() + descriptor_->oneof_decl_count())));
+ printer->Print("static const int $classname$_offsets_[$field_count$] = {\n",
+ "classname", classname_, "field_count",
+ SimpleItoa(std::max(1, descriptor_->field_count() +
+ descriptor_->oneof_decl_count())));
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1952,7 +1960,7 @@ GenerateSharedConstructorCode(io::Printer* printer) {
"_cached_size_ = 0;\n").c_str());
if (PreserveUnknownFields(descriptor_) &&
- !UseUnknownFieldSet(descriptor_->file())) {
+ !UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"_unknown_fields_.UnsafeSetDefault(\n"
" &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
@@ -1997,7 +2005,7 @@ GenerateSharedDestructorCode(io::Printer* printer) {
// Write the desctructor for _unknown_fields_ in lite runtime.
if (PreserveUnknownFields(descriptor_) &&
- !UseUnknownFieldSet(descriptor_->file())) {
+ !UseUnknownFieldSet(descriptor_->file(), options_)) {
if (SupportsArenas(descriptor_)) {
printer->Print(
"_unknown_fields_.Destroy(\n"
@@ -2028,11 +2036,11 @@ GenerateSharedDestructorCode(io::Printer* printer) {
}
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- "if (this != default_instance_) {\n",
- // Without.
- "if (this != &default_instance()) {\n");
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ "if (this != default_instance_) {\n",
+ // Without.
+ "if (this != &default_instance()) {\n");
// We need to delete all embedded messages.
// TODO(kenton): If we make unset messages point at default instances
@@ -2112,7 +2120,7 @@ GenerateStructors(io::Printer* printer) {
superclass =
DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
} else {
- superclass = SuperClassName(descriptor_);
+ superclass = SuperClassName(descriptor_, options_);
}
string initializer_with_arena = superclass + "()";
@@ -2120,7 +2128,7 @@ GenerateStructors(io::Printer* printer) {
initializer_with_arena += ",\n _extensions_(arena)";
}
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
initializer_with_arena += ",\n _internal_metadata_(arena)";
} else {
initializer_with_arena += ",\n _arena_ptr_(arena)";
@@ -2140,7 +2148,7 @@ GenerateStructors(io::Printer* printer) {
}
string initializer_null;
- initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
+ initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ?
", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)");
if (IsAnyMessage(descriptor_)) {
initializer_null += ", _any_metadata_(&type_url_, &value_)";
@@ -2194,24 +2202,23 @@ GenerateStructors(io::Printer* printer) {
if (!field->is_repeated() &&
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
(field->containing_oneof() == NULL ||
- HasDescriptorMethods(descriptor_->file()))) {
+ HasDescriptorMethods(descriptor_->file(), options_))) {
string name;
if (field->containing_oneof()) {
name = classname_ + "_default_oneof_instance_->";
}
name += FieldName(field);
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
- // Without.
- " $name$_ = const_cast< $type$*>(\n"
- " $type$::internal_default_instance());\n",
- // Vars.
- "name", name,
- "type", FieldMessageTypeName(field));
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
+ // Without.
+ " $name$_ = const_cast< $type$*>(\n"
+ " $type$::internal_default_instance());\n",
+ // Vars.
+ "name", name, "type", FieldMessageTypeName(field));
} else if (field->containing_oneof() &&
- HasDescriptorMethods(descriptor_->file())) {
+ HasDescriptorMethods(descriptor_->file(), options_)) {
field_generators_.get(descriptor_->field(i))
.GenerateConstructorCode(printer);
}
@@ -2227,10 +2234,10 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_,
"superclass", superclass,
"full_name", descriptor_->full_name());
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
",\n _internal_metadata_(NULL)");
- } else if (!UseUnknownFieldSet(descriptor_->file())) {
+ } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(",\n _arena_ptr_(NULL)");
}
if (IsAnyMessage(descriptor_)) {
@@ -2278,7 +2285,7 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_);
// Only generate this member if it's not disabled.
- if (HasDescriptorMethods(descriptor_->file()) &&
+ if (HasDescriptorMethods(descriptor_->file(), options_) &&
!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
@@ -2296,14 +2303,14 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_);
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " if (default_instance_ == NULL) $adddescriptorsname$();\n",
- // Without.
- " $adddescriptorsname$();\n",
- // Vars.
- "adddescriptorsname",
- GlobalAddDescriptorsName(descriptor_->file()->name()));
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " if (default_instance_ == NULL) $adddescriptorsname$();\n",
+ // Without.
+ " $adddescriptorsname$();\n",
+ // Vars.
+ "adddescriptorsname",
+ GlobalAddDescriptorsName(descriptor_->file()->name()));
printer->Print(
" return *default_instance_;\n"
@@ -2345,8 +2352,10 @@ static int popcnt(uint32 n) {
void MessageGenerator::
GenerateClear(io::Printer* printer) {
- printer->Print("void $classname$::Clear() {\n",
- "classname", classname_);
+ printer->Print(
+ "void $classname$::Clear() {\n"
+ "// @@protoc_insertion_point(message_clear_start:$full_name$)\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
// Step 1: Extensions
@@ -2383,8 +2392,16 @@ GenerateClear(io::Printer* printer) {
// positions of two fields in the Message.
// ZR_ zeroes a non-empty range of fields via memset.
const char* macros =
+ "#if defined(__clang__)\n"
+ "#define ZR_HELPER_(f) \\\n"
+ " _Pragma(\"clang diagnostic push\") \\\n"
+ " _Pragma(\"clang diagnostic ignored \\\"-Winvalid-offsetof\\\"\") \\\n"
+ " __builtin_offsetof($classname$, f) \\\n"
+ " _Pragma(\"clang diagnostic pop\")\n"
+ "#else\n"
"#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
- " &reinterpret_cast<$classname$*>(16)->f)\n\n"
+ " &reinterpret_cast<$classname$*>(16)->f)\n"
+ "#endif\n\n"
"#define ZR_(first, last) do {\\\n"
" ::memset(&first, 0,\\\n"
" ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
@@ -2512,7 +2529,7 @@ GenerateClear(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"if (_internal_metadata_.have_unknown_fields()) {\n"
" mutable_unknown_fields()->Clear();\n"
@@ -2542,10 +2559,13 @@ GenerateOneofClear(io::Printer* printer) {
map<string, string> oneof_vars;
oneof_vars["classname"] = classname_;
oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
+ oneof_vars["full_name"] = descriptor_->full_name();
string message_class;
printer->Print(oneof_vars,
- "void $classname$::clear_$oneofname$() {\n");
+ "void $classname$::clear_$oneofname$() {\n"
+ "// @@protoc_insertion_point(one_of_clear_start:"
+ "$full_name$)\n");
printer->Indent();
printer->Print(oneof_vars,
"switch($oneofname$_case()) {\n");
@@ -2628,7 +2648,7 @@ GenerateSwap(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- if (HasGeneratedMethods(descriptor_->file())) {
+ if (HasGeneratedMethods(descriptor_->file(), options_)) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateSwappingCode(printer);
@@ -2649,19 +2669,15 @@ GenerateSwap(io::Printer* printer) {
}
}
- if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
+ // Ignore PreserveUnknownFields here - always swap internal_metadata as it
+ // may contain more than just unknown fields.
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+ printer->Print(
"_internal_metadata_.Swap(&other->_internal_metadata_);\n");
- } else {
- printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
- }
} else {
- // Still swap internal_metadata as it may contain more than just
- // unknown fields.
- printer->Print(
- "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+ printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
}
+
printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
if (descriptor_->extension_range_count() > 0) {
printer->Print("_extensions_.Swap(&other->_extensions_);\n");
@@ -2676,13 +2692,15 @@ GenerateSwap(io::Printer* printer) {
void MessageGenerator::
GenerateMergeFrom(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
// Generate the generalized MergeFrom (aka that which takes in the Message
// base class as a parameter).
printer->Print(
- "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
- " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
- "classname", classname_);
+ "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
+ "// @@protoc_insertion_point(generalized_merge_from_start:"
+ "$full_name$)\n"
+ " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
// Cast the message to the proper type. If we find that the message is
@@ -2694,11 +2712,15 @@ GenerateMergeFrom(io::Printer* printer) {
" ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
" &from);\n"
"if (source == NULL) {\n"
+ "// @@protoc_insertion_point(generalized_merge_from_cast_fail:"
+ "$full_name$)\n"
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
"} else {\n"
+ "// @@protoc_insertion_point(generalized_merge_from_cast_success:"
+ "$full_name$)\n"
" MergeFrom(*source);\n"
"}\n",
- "classname", classname_);
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Outdent();
printer->Print("}\n\n");
@@ -2715,9 +2737,11 @@ GenerateMergeFrom(io::Printer* printer) {
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
printer->Print(
- "void $classname$::MergeFrom(const $classname$& from) {\n"
- " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
- "classname", classname_);
+ "void $classname$::MergeFrom(const $classname$& from) {\n"
+ "// @@protoc_insertion_point(class_specific_merge_from_start:"
+ "$full_name$)\n"
+ " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
// Merge Repeated fields. These fields do not require a
@@ -2818,7 +2842,7 @@ GenerateMergeFrom(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"if (from._internal_metadata_.have_unknown_fields()) {\n"
" mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
@@ -2837,12 +2861,14 @@ GenerateMergeFrom(io::Printer* printer) {
void MessageGenerator::
GenerateCopyFrom(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_->file())) {
+ if (HasDescriptorMethods(descriptor_->file(), options_)) {
// Generate the generalized CopyFrom (aka that which takes in the Message
// base class as a parameter).
printer->Print(
- "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
- "classname", classname_);
+ "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n"
+ "// @@protoc_insertion_point(generalized_copy_from_start:"
+ "$full_name$)\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
printer->Print(
@@ -2856,8 +2882,10 @@ GenerateCopyFrom(io::Printer* printer) {
// Generate the class-specific CopyFrom.
printer->Print(
- "void $classname$::CopyFrom(const $classname$& from) {\n",
- "classname", classname_);
+ "void $classname$::CopyFrom(const $classname$& from) {\n"
+ "// @@protoc_insertion_point(class_specific_copy_from_start:"
+ "$full_name$)\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
printer->Print(
@@ -2879,15 +2907,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
"classname", classname_);
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " return _extensions_.ParseMessageSet(input, default_instance_,\n"
- " mutable_unknown_fields());\n",
- // Without.
- " return _extensions_.ParseMessageSet(input, &default_instance(),\n"
- " mutable_unknown_fields());\n",
- // Vars.
- "classname", classname_);
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " return _extensions_.ParseMessageSet(input, default_instance_,\n"
+ " mutable_unknown_fields());\n",
+ // Without.
+ " return _extensions_.ParseMessageSet(input, &default_instance(),\n"
+ " mutable_unknown_fields());\n",
+ // Vars.
+ "classname", classname_);
printer->Print(
"}\n");
@@ -2897,11 +2925,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Print(
"bool $classname$::MergePartialFromCodedStream(\n"
" ::google::protobuf::io::CodedInputStream* input) {\n"
- "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n"
+ "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n"
" ::google::protobuf::uint32 tag;\n",
"classname", classname_);
- if (!UseUnknownFieldSet(descriptor_->file())) {
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file(), options_)) {
// Use LazyStringOutputString to avoid initializing unknown fields string
// unless it is actually needed. For the same reason, disable eager refresh
// on the CodedOutputStream.
@@ -3129,32 +3158,32 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
printer->Print(") {\n");
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " mutable_unknown_fields()));\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " mutable_unknown_fields()));\n");
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " mutable_unknown_fields()));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " mutable_unknown_fields()));\n");
} else {
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " &unknown_fields_stream));\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " &unknown_fields_stream));\n");
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " &unknown_fields_stream));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " &unknown_fields_stream));\n");
}
} else {
PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
+ descriptor_->file(), options_, printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
}
printer->Print(
" continue;\n"
@@ -3163,7 +3192,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// We really don't recognize this tag. Skip it.
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
" input, tag, mutable_unknown_fields()));\n");
@@ -3256,7 +3285,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
" ::google::protobuf::io::CodedOutputStream* output) const {\n"
" _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
"classname", classname_);
- GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
+ GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
printer->Print(
" ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
" unknown_fields(), output);\n");
@@ -3296,7 +3325,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
" target =\n"
" _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
"classname", classname_);
- GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
+ GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
printer->Print(
" target = ::google::protobuf::internal::WireFormat::\n"
" SerializeUnknownMessageSetItemsToArray(\n"
@@ -3362,7 +3391,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
printer->Indent();
if (to_array) {
@@ -3429,10 +3458,11 @@ GenerateByteSize(io::Printer* printer) {
if (descriptor_->options().message_set_wire_format()) {
// Special-case MessageSet.
printer->Print(
- "int $classname$::ByteSize() const {\n"
- " int total_size = _extensions_.MessageSetByteSize();\n",
- "classname", classname_);
- GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
+ "int $classname$::ByteSize() const {\n"
+ "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
+ " int total_size = _extensions_.MessageSetByteSize();\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
+ GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
printer->Print(
"if (_internal_metadata_.have_unknown_fields()) {\n"
" total_size += ::google::protobuf::internal::WireFormat::\n"
@@ -3451,8 +3481,10 @@ GenerateByteSize(io::Printer* printer) {
// Emit a function (rarely used, we hope) that handles the required fields
// by checking for each one individually.
printer->Print(
- "int $classname$::RequiredFieldsByteSizeFallback() const {\n",
- "classname", classname_);
+ "int $classname$::RequiredFieldsByteSizeFallback() const {\n"
+ "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
+ "$full_name$)\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
printer->Print("int total_size = 0;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -3475,8 +3507,9 @@ GenerateByteSize(io::Printer* printer) {
}
printer->Print(
- "int $classname$::ByteSize() const {\n",
- "classname", classname_);
+ "int $classname$::ByteSize() const {\n"
+ "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n",
+ "classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
printer->Print(
"int total_size = 0;\n"
@@ -3652,7 +3685,7 @@ GenerateByteSize(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"if (_internal_metadata_.have_unknown_fields()) {\n"
" total_size +=\n"
@@ -3718,8 +3751,8 @@ GenerateIsInitialized(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
- !ShouldIgnoreRequiredFieldCheck(field) &&
- HasRequiredFields(field->message_type())) {
+ !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+ HasRequiredFields(field->message_type(), options_)) {
if (field->is_repeated()) {
printer->Print(
"if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 8e19a3f0..31223e13 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -67,9 +67,13 @@ class MessageGenerator {
// Header stuff.
// Return names for foward declarations of this class and all its nested
- // types.
- void FillMessageForwardDeclarations(set<string>* class_names);
- void FillEnumForwardDeclarations(set<string>* enum_names);
+ // types. A given key in {class,enum}_names will map from a class name to the
+ // descriptor that was responsible for its inclusion in the map. This can be
+ // used to associate the descriptor with the code generated for it.
+ void FillMessageForwardDeclarations(
+ map<string, const Descriptor*>* class_names);
+ void FillEnumForwardDeclarations(
+ map<string, const EnumDescriptor*>* enum_names);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b4545892..332c0264 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -53,10 +53,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["non_null_ptr_to_name"] =
StrCat("this->", (*variables)["name"], "_");
}
- (*variables)["stream_writer"] = (*variables)["declared_type"] +
- (HasFastArraySerialization(descriptor->message_type()->file()) ?
- "MaybeToArray" :
- "");
+ (*variables)["stream_writer"] =
+ (*variables)["declared_type"] +
+ (HasFastArraySerialization(descriptor->message_type()->file(), options)
+ ? "MaybeToArray"
+ : "");
// NOTE: Escaped here to unblock proto1->proto2 migration.
// TODO(liujisi): Extend this to apply for other conflicting methods.
(*variables)["release_name"] =
@@ -77,11 +78,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// ===================================================================
-MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor),
- dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(options),
+ descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -95,7 +96,7 @@ GeneratePrivateMembers(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateGetterDeclaration(io::Printer* printer) const {
printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n");
+ "$deprecated_attr$const $type$& $name$() const;\n");
}
void MessageFieldGenerator::
@@ -105,9 +106,9 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const {
}
// Arena manipulation code is out-of-line in the derived message class.
printer->Print(variables_,
- "$type$* mutable_$name$()$deprecation$;\n"
- "$type$* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ "$deprecated_attr$$type$* mutable_$name$();\n"
+ "$deprecated_attr$$type$* $release_name$();\n"
+ "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
}
void MessageFieldGenerator::
@@ -115,28 +116,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
"private:\n"
- "void _slow_mutable_$name$()$deprecation$;\n");
+ "void _slow_mutable_$name$();\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
"void _slow_set_allocated_$name$(\n"
- " ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
+ " ::google::protobuf::Arena* message_arena, $type$** $name$);\n");
}
printer->Print(variables_,
- "$type$* _slow_$release_name$()$deprecation$;\n"
+ "$type$* _slow_$release_name$();\n"
"public:\n");
}
GenerateGetterDeclaration(printer);
if (!dependent_field_) {
printer->Print(variables_,
- "$type$* mutable_$name$()$deprecation$;\n"
- "$type$* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ "$deprecated_attr$$type$* mutable_$name$();\n"
+ "$deprecated_attr$$type$* $release_name$();\n"
+ "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
}
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
- "void unsafe_arena_set_allocated_$name$(\n"
- " $type$* $name$)$deprecation$;\n");
+ "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n"
+ "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$);\n");
}
}
@@ -167,6 +168,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" }\n"
"}\n"
"$type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
@@ -246,6 +248,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"template <class T>\n"
"inline $type$* $dependent_classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
" $clear_hasbit$\n"
" if ($this_message$GetArenaNoVirtual() != NULL) {\n"
@@ -305,6 +308,7 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"template <class T>\n"
"inline $type$* $dependent_classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
" $dependent_typename$* temp = $name$_;\n"
@@ -349,11 +353,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
- variables, descriptor_->file(), printer,
- // With static initializers.
- " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
- // Without.
- " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+ variables, descriptor_->file(), options_, printer,
+ // With static initializers.
+ " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
+ // Without.
+ " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
printer->Print(variables, "}\n");
if (dependent_field_) {
@@ -373,6 +377,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n"
"$inline$"
"$type$* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" if (GetArenaNoVirtual() != NULL) {\n"
" return _slow_$release_name$();\n"
@@ -426,6 +431,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n"
"$inline$"
"$type$* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
@@ -547,7 +553,7 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const {
return;
}
printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n");
+ "$deprecated_attr$const $type$& $name$() const;\n");
MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
}
@@ -560,7 +566,7 @@ GenerateGetterDeclaration(io::Printer* printer) const {
return;
}
printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n");
+ "$deprecated_attr$const $type$& $name$() const;\n");
}
void MessageOneofFieldGenerator::
@@ -651,6 +657,7 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
"$tmpl$"
"$inline$"
"$type$* $dependent_classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" if ($this_message$has_$name$()) {\n"
" $this_message$clear_has_$oneof_name$();\n"
" if ($this_message$GetArenaNoVirtual() != NULL) {\n"
@@ -706,6 +713,8 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
"$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_release"
+ ":$full_name$)\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
@@ -744,6 +753,7 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
"$tmpl$"
"$inline$"
"$type$* $dependent_classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" if ($this_message$has_$name$()) {\n"
" $this_message$clear_has_$oneof_name$();\n"
" $dependent_typename$* temp = $field_member$;\n"
@@ -805,12 +815,12 @@ GenerateConstructorCode(io::Printer* printer) const {
// ===================================================================
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor),
- dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
- dependent_getter_(dependent_field_ && options.safe_boundary_check) {
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(options),
+ descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+ dependent_getter_(dependent_field_ && options.safe_boundary_check) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -825,23 +835,23 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "$type$* mutable_$name$(int index)$deprecation$;\n"
- "$type$* add_$name$()$deprecation$;\n");
+ "$deprecated_attr$$type$* mutable_$name$(int index);\n"
+ "$deprecated_attr$$type$* add_$name$();\n");
if (dependent_getter_) {
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- " $name$() const$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const;\n");
}
printer->Print(variables_,
- "::google::protobuf::RepeatedPtrField< $type$ >*\n"
- " mutable_$name$()$deprecation$;\n");
+ "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ " mutable_$name$();\n");
}
void RepeatedMessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
if (dependent_getter_) {
printer->Print(variables_,
- "const $type$& $name$(int index) const$deprecation$;\n");
+ "$deprecated_attr$const $type$& $name$(int index) const;\n");
}
if (dependent_field_) {
InternalGenerateTypeDependentAccessorDeclarations(printer);
@@ -852,15 +862,15 @@ void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
if (!dependent_getter_) {
printer->Print(variables_,
- "const $type$& $name$(int index) const$deprecation$;\n");
+ "$deprecated_attr$const $type$& $name$(int index) const;\n");
}
if (!dependent_field_) {
InternalGenerateTypeDependentAccessorDeclarations(printer);
}
if (!dependent_getter_) {
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- " $name$() const$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const;\n");
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 35efd0fa..d8d9279c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -46,8 +46,8 @@ namespace cpp {
class MessageFieldGenerator : public FieldGenerator {
public:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~MessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -83,8 +83,8 @@ class MessageFieldGenerator : public FieldGenerator {
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
- explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -110,8 +110,8 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 4463f200..ab1d2ed3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -43,11 +43,19 @@ namespace cpp {
// Generator options (see generator.cc for a description of each):
struct Options {
- Options() : safe_boundary_check(false), proto_h(false) {
- }
+ Options()
+ : safe_boundary_check(false),
+ proto_h(false),
+ annotate_headers(false),
+ enforce_lite(false) {}
+
string dllexport_decl;
bool safe_boundary_check;
bool proto_h;
+ bool annotate_headers;
+ bool enforce_lite;
+ string annotation_pragma_name;
+ string annotation_guard_name;
};
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index d1efbfe6..34a41d82 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -44,9 +44,10 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 9f929d37..650f0381 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -100,10 +100,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// ===================================================================
-PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
}
@@ -117,8 +116,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "$type$ $name$() const$deprecation$;\n"
- "void set_$name$($type$ value)$deprecation$;\n");
+ "$deprecated_attr$$type$ $name$() const;\n"
+ "$deprecated_attr$void set_$name$($type$ value);\n");
}
void PrimitiveFieldGenerator::
@@ -256,10 +255,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
// ===================================================================
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
if (descriptor->is_packed()) {
@@ -277,7 +275,8 @@ void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
- if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) {
+ if (descriptor_->is_packed() &&
+ HasGeneratedMethods(descriptor_->file(), options_)) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
@@ -286,14 +285,14 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "$type$ $name$(int index) const$deprecation$;\n"
- "void set_$name$(int index, $type$ value)$deprecation$;\n"
- "void add_$name$($type$ value)$deprecation$;\n");
+ "$deprecated_attr$$type$ $name$(int index) const;\n"
+ "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
+ "$deprecated_attr$void add_$name$($type$ value);\n");
printer->Print(variables_,
- "const ::google::protobuf::RepeatedField< $type$ >&\n"
- " $name$() const$deprecation$;\n"
- "::google::protobuf::RepeatedField< $type$ >*\n"
- " mutable_$name$()$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " $name$() const;\n"
+ "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
+ " mutable_$name$();\n");
}
void RepeatedPrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index fcd7d684..655ebde4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -46,8 +46,8 @@ namespace cpp {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -74,8 +74,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
- explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~PrimitiveOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -92,8 +92,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 6b0821a6..1d743457 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -76,10 +76,9 @@ void SetStringVariables(const FieldDescriptor* descriptor,
// ===================================================================
-StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
@@ -140,19 +139,19 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "const ::std::string& $name$() const$deprecation$;\n"
- "void set_$name$(const ::std::string& value)$deprecation$;\n"
- "void set_$name$(const char* value)$deprecation$;\n"
- "void set_$name$(const $pointer_type$* value, size_t size)"
- "$deprecation$;\n"
- "::std::string* mutable_$name$()$deprecation$;\n"
- "::std::string* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+ "$deprecated_attr$const ::std::string& $name$() const;\n"
+ "$deprecated_attr$void set_$name$(const ::std::string& value);\n"
+ "$deprecated_attr$void set_$name$(const char* value);\n"
+ "$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
+ ";\n"
+ "$deprecated_attr$::std::string* mutable_$name$();\n"
+ "$deprecated_attr$::std::string* $release_name$();\n"
+ "$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
- "void unsafe_arena_set_allocated_$name$(\n"
- " ::std::string* $name$)$deprecation$;\n");
+ "$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n"
+ "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
+ " ::std::string* $name$);\n");
}
@@ -199,10 +198,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
"}\n"
"$inline$ ::std::string* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
"}\n"
"$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" $clear_hasbit$\n"
" return $name$_.UnsafeArenaRelease($default_variable$,\n"
@@ -228,7 +229,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" }\n"
" $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
" $name$, GetArenaNoVirtual());\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+ "$full_name$)\n"
"}\n");
} else {
// No-arena case.
@@ -261,6 +263,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $name$_.MutableNoArena($default_variable$);\n"
"}\n"
"$inline$ ::std::string* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" return $name$_.ReleaseNoArena($default_variable$);\n"
"}\n"
@@ -369,7 +372,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, true, variables_,
+ descriptor_, options_, true, variables_,
"this->$name$().data(), this->$name$().length(),\n", printer);
}
}
@@ -378,7 +381,7 @@ void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, false, variables_,
+ descriptor_, options_, false, variables_,
"this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
@@ -390,7 +393,7 @@ void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, false, variables_,
+ descriptor_, options_, false, variables_,
"this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
@@ -477,6 +480,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"}\n"
"$inline$ ::std::string* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.Release($default_variable$,\n"
@@ -486,6 +490,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" }\n"
"}\n"
"$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
@@ -519,7 +524,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
"$name$, GetArenaNoVirtual());\n"
" }\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+ "$full_name$)\n"
"}\n");
} else {
// No-arena case.
@@ -572,6 +578,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
"}\n"
"$inline$ ::std::string* $classname$::$release_name$() {\n"
+ " // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
@@ -658,7 +665,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, true, variables_,
+ descriptor_, options_, true, variables_,
"this->$name$().data(), this->$name$().length(),\n", printer);
}
}
@@ -666,10 +673,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
// ===================================================================
-RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
+ const FieldDescriptor* descriptor, const Options& options)
+ : FieldGenerator(options), descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
@@ -696,24 +702,24 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "const ::std::string& $name$(int index) const$deprecation$;\n"
- "::std::string* mutable_$name$(int index)$deprecation$;\n"
- "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
- "void set_$name$(int index, const char* value)$deprecation$;\n"
+ "$deprecated_attr$const ::std::string& $name$(int index) const;\n"
+ "$deprecated_attr$::std::string* mutable_$name$(int index);\n"
+ "$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n"
+ "$deprecated_attr$void set_$name$(int index, const char* value);\n"
""
- "void set_$name$(int index, const $pointer_type$* value, size_t size)"
- "$deprecation$;\n"
- "::std::string* add_$name$()$deprecation$;\n"
- "void add_$name$(const ::std::string& value)$deprecation$;\n"
- "void add_$name$(const char* value)$deprecation$;\n"
- "void add_$name$(const $pointer_type$* value, size_t size)"
- "$deprecation$;\n");
+ "$deprecated_attr$void set_$name$("
+ "int index, const $pointer_type$* value, size_t size);\n"
+ "$deprecated_attr$::std::string* add_$name$();\n"
+ "$deprecated_attr$void add_$name$(const ::std::string& value);\n"
+ "$deprecated_attr$void add_$name$(const char* value);\n"
+ "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)"
+ ";\n");
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
- "$deprecation$;\n"
- "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
- "$deprecation$;\n");
+ "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
+ "const;\n"
+ "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+ ";\n");
if (unknown_ctype) {
printer->Outdent();
@@ -752,6 +758,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"$inline$ ::std::string* $classname$::add_$name$() {\n"
+ " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
" return $name$_.Add();\n"
"}\n"
"$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
@@ -807,7 +814,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" input, this->add_$name$()));\n");
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, true, variables_,
+ descriptor_, options_, true, variables_,
"this->$name$(this->$name$_size() - 1).data(),\n"
"this->$name$(this->$name$_size() - 1).length(),\n",
printer);
@@ -821,7 +828,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Indent();
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, false, variables_,
+ descriptor_, options_, false, variables_,
"this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
printer->Outdent();
@@ -838,7 +845,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Indent();
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
- descriptor_, false, variables_,
+ descriptor_, options_, false, variables_,
"this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
printer->Outdent();
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 616e2067..cb4e8772 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -46,8 +46,8 @@ namespace cpp {
class StringFieldGenerator : public FieldGenerator {
public:
- explicit StringFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~StringFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -79,8 +79,8 @@ class StringFieldGenerator : public FieldGenerator {
class StringOneofFieldGenerator : public StringFieldGenerator {
public:
- explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ StringOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~StringOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -99,8 +99,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
class RepeatedStringFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options);
+ RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedStringFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 9942a343..5d82946d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -82,7 +82,6 @@
namespace google {
namespace protobuf {
-using internal::NewPermanentCallback;
namespace compiler {
namespace cpp {
@@ -1253,7 +1252,7 @@ class GeneratedServiceTest : public testing::Test {
foo_(descriptor_->FindMethodByName("Foo")),
bar_(descriptor_->FindMethodByName("Bar")),
stub_(&mock_channel_),
- done_(NewPermanentCallback(&DoNothing)) {}
+ done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {}
virtual void SetUp() {
ASSERT_TRUE(foo_ != NULL);
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index 422eb73b..edd30780 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -41,9 +41,10 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
namespace google {
namespace protobuf {
@@ -51,6 +52,189 @@ namespace compiler {
namespace cpp {
namespace {
+// A CodeGenerator that captures the FileDescriptor it's passed as a
+// FileDescriptorProto.
+class DescriptorCapturingGenerator : public CodeGenerator {
+ public:
+ // Does not own file; file must outlive the Generator.
+ explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
+ : file_(file) {}
+
+ virtual bool Generate(const FileDescriptor* file, const string& parameter,
+ GeneratorContext* context, string* error) const {
+ file->CopyTo(file_);
+ return true;
+ }
+
+ private:
+ FileDescriptorProto* file_;
+};
+
+class CppMetadataTest : public ::testing::Test {
+ public:
+ // Adds a file with name `filename` and content `data`.
+ void AddFile(const string& filename, const string& data) {
+ GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
+ true));
+ }
+
+ // Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
+ // code from the previously added file with name `filename`. Returns true on
+ // success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
+ // pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
+ bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
+ string* pb_h, GeneratedCodeInfo* pb_h_info,
+ string* proto_h, GeneratedCodeInfo* proto_h_info,
+ string* pb_cc) {
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ CppGenerator cpp_generator;
+ DescriptorCapturingGenerator capturing_generator(file);
+ cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+ cli.RegisterGenerator("--capture_out", &capturing_generator, "");
+
+ string proto_path = "-I" + TestTempDir();
+ string cpp_out =
+ "--cpp_out=annotate_headers=true,"
+ "annotation_pragma_name=pragma_name,"
+ "annotation_guard_name=guard_name:" +
+ TestTempDir();
+ string capture_out = "--capture_out=" + TestTempDir();
+
+ const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(),
+ capture_out.c_str(), filename.c_str()};
+
+ if (cli.Run(5, argv) != 0) {
+ return false;
+ }
+
+ string output_base = TestTempDir() + "/" + StripProto(filename);
+
+ if (pb_cc != NULL) {
+ GOOGLE_CHECK_OK(
+ File::GetContents(output_base + ".pb.cc", pb_cc, true));
+ }
+
+ if (pb_h != NULL && pb_h_info != NULL) {
+ GOOGLE_CHECK_OK(
+ File::GetContents(output_base + ".pb.h", pb_h, true));
+ if (!DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
+ return false;
+ }
+ }
+
+ if (proto_h != NULL && proto_h_info != NULL) {
+ GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
+ true));
+ if (!DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ // Decodes GeneratedCodeInfo stored in path and copies it to info.
+ // Returns true on success.
+ bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
+ string data;
+ GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
+ io::ArrayInputStream input(data.data(), data.size());
+ return info->ParseFromZeroCopyStream(&input);
+ }
+};
+
+const char kSmallTestFile[] =
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "enum Enum { VALUE = 0; }\n"
+ "message Message { }\n";
+
+// Finds the Annotation for a given source file and path (or returns null if it
+// couldn't).
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+ const GeneratedCodeInfo& info, const string& source_file,
+ const vector<int>& path) {
+ for (int i = 0; i < info.annotation_size(); ++i) {
+ const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
+ if (annotation->source_file() != source_file ||
+ annotation->path_size() != path.size()) {
+ continue;
+ }
+ int node = 0;
+ for (; node < path.size(); ++node) {
+ if (annotation->path(node) != path[node]) {
+ break;
+ }
+ }
+ if (node == path.size()) {
+ return annotation;
+ }
+ }
+ return NULL;
+}
+
+// Returns true if the provided annotation covers a given substring in
+// file_content.
+bool AnnotationMatchesSubstring(const string& file_content,
+ const GeneratedCodeInfo::Annotation* annotation,
+ const string& expected_text) {
+ uint32 begin = annotation->begin();
+ uint32 end = annotation->end();
+ if (end < begin || end > file_content.size()) {
+ return false;
+ }
+ return file_content.substr(begin, end - begin) == expected_text;
+}
+
+TEST_F(CppMetadataTest, CapturesEnumNames) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ string pb_h;
+ AddFile("test.proto", kSmallTestFile);
+ EXPECT_TRUE(
+ CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+ EXPECT_EQ("Enum", file.enum_type(0).name());
+ vector<int> enum_path;
+ enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+ enum_path.push_back(0);
+ const GeneratedCodeInfo::Annotation* enum_annotation =
+ FindAnnotationOnPath(info, "test.proto", enum_path);
+ EXPECT_TRUE(NULL != enum_annotation);
+ EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
+}
+
+TEST_F(CppMetadataTest, AddsPragma) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ string pb_h;
+ AddFile("test.proto", kSmallTestFile);
+ EXPECT_TRUE(
+ CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+ EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
+ EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
+ string::npos);
+}
+
+TEST_F(CppMetadataTest, CapturesMessageNames) {
+ FileDescriptorProto file;
+ GeneratedCodeInfo info;
+ string pb_h;
+ AddFile("test.proto", kSmallTestFile);
+ EXPECT_TRUE(
+ CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+ EXPECT_EQ("Message", file.message_type(0).name());
+ vector<int> message_path;
+ message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+ message_path.push_back(0);
+ const GeneratedCodeInfo::Annotation* message_annotation =
+ FindAnnotationOnPath(info, "test.proto", message_path);
+ EXPECT_TRUE(NULL != message_annotation);
+ EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
+}
+
} // namespace
} // namespace cpp
} // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 56681989..bdfcc2be 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -41,6 +41,7 @@
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_enum.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
using google::protobuf::internal::scoped_ptr;
@@ -49,8 +50,8 @@ namespace protobuf {
namespace compiler {
namespace csharp {
-EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) :
- SourceGeneratorBase(descriptor->file()),
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
+ SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor) {
}
@@ -64,11 +65,24 @@ void EnumGenerator::Generate(io::Printer* printer) {
"access_level", class_access_level(),
"name", descriptor_->name());
printer->Indent();
+ std::set<string> used_names;
for (int i = 0; i < descriptor_->value_count(); i++) {
WriteEnumValueDocComment(printer, descriptor_->value(i));
- printer->Print("$name$ = $number$,\n",
- "name", descriptor_->value(i)->name(),
- "number", SimpleItoa(descriptor_->value(i)->number()));
+ string original_name = descriptor_->value(i)->name();
+ string name = options()->legacy_enum_values
+ ? descriptor_->value(i)->name()
+ : GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
+ // Make sure we don't get any duplicate names due to prefix removal.
+ while (!used_names.insert(name).second) {
+ // It's possible we'll end up giving this warning multiple times, but that's better than not at all.
+ GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
+ << ") in " << descriptor_->name() << "; adding underscore to distinguish";
+ name += "_";
+ }
+ printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
+ "original_name", original_name,
+ "name", name,
+ "number", SimpleItoa(descriptor_->value(i)->number()));
}
printer->Outdent();
printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h
index 2cf2fad4..8925cdf2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.h
@@ -43,7 +43,7 @@ namespace csharp {
class EnumGenerator : public SourceGeneratorBase {
public:
- EnumGenerator(const EnumDescriptor* descriptor);
+ EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
~EnumGenerator();
void Generate(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index d38fb1ed..67c0b596 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
namespace google {
@@ -46,8 +47,8 @@ namespace compiler {
namespace csharp {
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+ int fieldOrdinal, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
}
EnumFieldGenerator::~EnumFieldGenerator() {
@@ -80,9 +81,9 @@ void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
}
-EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 08364157..9b7669ba 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -43,7 +43,9 @@ namespace csharp {
class EnumFieldGenerator : public PrimitiveFieldGenerator {
public:
- EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ EnumFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~EnumFieldGenerator();
virtual void GenerateCodecCode(io::Printer* printer);
@@ -57,7 +59,9 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator {
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
public:
- EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~EnumOneofFieldGenerator();
virtual void GenerateParsingCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 5df43d3f..e3c34040 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -94,14 +94,15 @@ void FieldGeneratorBase::SetCommonFieldVariables(
void FieldGeneratorBase::SetCommonOneofFieldVariables(
map<string, string>* variables) {
(*variables)["oneof_name"] = oneof_name();
- (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() +
+ (*variables)["has_property_check"] =
+ oneof_name() + "Case_ == " + oneof_property_name() +
"OneofCase." + property_name();
(*variables)["oneof_property_name"] = oneof_property_name();
}
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : SourceGeneratorBase(descriptor->file()),
+ int fieldOrdinal, const Options* options)
+ : SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor),
fieldOrdinal_(fieldOrdinal) {
SetCommonFieldVariables(&variables_);
@@ -158,10 +159,11 @@ std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
- const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+ const FieldDescriptor* wrapped_field =
+ descriptor->message_type()->field(0);
string wrapped_field_type_name = type_name(wrapped_field);
- // String and ByteString go to the same type; other wrapped types go to the
- // nullable equivalent.
+ // 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;
@@ -304,7 +306,9 @@ std::string FieldGeneratorBase::default_value() {
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
- return type_name() + "." + descriptor->default_value_enum()->name();
+ // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
+ // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
+ return "0";
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index d83543bd..4109f3ca 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -44,7 +44,9 @@ namespace csharp {
class FieldGeneratorBase : public SourceGeneratorBase {
public:
- FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
+ FieldGeneratorBase(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options* options);
~FieldGeneratorBase();
virtual void GenerateCloningCode(io::Printer* printer) = 0;
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 825de542..d74e8c88 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -41,6 +41,7 @@
#include <google/protobuf/compiler/csharp/csharp_generator.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
using google::protobuf::internal::scoped_ptr;
@@ -51,8 +52,9 @@ namespace compiler {
namespace csharp {
void GenerateFile(const google::protobuf::FileDescriptor* file,
- io::Printer* printer) {
- ReflectionClassGenerator reflectionClassGenerator(file);
+ io::Printer* printer,
+ const Options* options) {
+ ReflectionClassGenerator reflectionClassGenerator(file, options);
reflectionClassGenerator.Generate(printer);
}
@@ -71,15 +73,19 @@ bool Generator::Generate(
return false;
}
- std::string file_extension = ".cs";
- std::string base_namespace = "";
- bool generate_directories = false;
+ struct Options cli_options;
+
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "file_extension") {
- file_extension = options[i].second;
+ cli_options.file_extension = options[i].second;
} else if (options[i].first == "base_namespace") {
- base_namespace = options[i].second;
- generate_directories = true;
+ 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 == "legacy_enum_values") {
+ // TODO: Remove this before final release
+ cli_options.legacy_enum_values = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@@ -87,7 +93,12 @@ bool Generator::Generate(
}
string filename_error = "";
- std::string filename = GetOutputFile(file, file_extension, generate_directories, base_namespace, &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;
@@ -96,7 +107,7 @@ bool Generator::Generate(
generator_context->Open(filename));
io::Printer printer(output.get(), '$');
- GenerateFile(file, &printer);
+ GenerateFile(file, &printer, &cli_options);
return true;
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
index 7ef7df42..5755fee0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -30,8 +30,8 @@
#include <memory>
-#include <google/protobuf/compiler/ruby/ruby_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
@@ -45,7 +45,23 @@ namespace compiler {
namespace csharp {
namespace {
-// TODO(jtattermusch): add some tests.
+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
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index c51fe44b..6c154c5a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
#include <google/protobuf/compiler/csharp/csharp_map_field.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
@@ -127,7 +128,8 @@ std::string GetFileNameBase(const FileDescriptor* descriptor) {
}
std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
- // TODO: Detect collisions with existing messages, and append an underscore if necessary.
+ // TODO: Detect collisions with existing messages,
+ // and append an underscore if necessary.
return GetFileNameBase(descriptor) + "Reflection";
}
@@ -176,6 +178,104 @@ 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) {
+ 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;
+}
+
std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
std::string result = GetFileNamespace(file);
if (result != "") {
@@ -351,49 +451,50 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
}
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal) {
+ int fieldOrdinal,
+ 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, fieldOrdinal);
+ return new MapFieldGenerator(descriptor, fieldOrdinal, options);
} else {
- return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+ return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
}
} else {
if (IsWrapperType(descriptor)) {
if (descriptor->containing_oneof()) {
- return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+ return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
} else {
- return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+ return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
}
} else {
if (descriptor->containing_oneof()) {
- return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+ return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
} else {
- return new MessageFieldGenerator(descriptor, fieldOrdinal);
+ return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
}
}
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
- return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
+ return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
} else {
if (descriptor->containing_oneof()) {
- return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+ return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
} else {
- return new EnumFieldGenerator(descriptor, fieldOrdinal);
+ return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
}
}
default:
if (descriptor->is_repeated()) {
- return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
+ return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
} else {
if (descriptor->containing_oneof()) {
- return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+ return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
} else {
- return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+ return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
}
}
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index e96e7938..1563ca7e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -36,6 +36,7 @@
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#include <string>
+#include <google/protobuf/stubs/port.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/code_generator.h>
@@ -46,6 +47,7 @@ namespace protobuf {
namespace compiler {
namespace csharp {
+struct Options;
class FieldGeneratorBase;
// TODO: start using this enum.
@@ -82,7 +84,9 @@ 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);
+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);
@@ -90,22 +94,28 @@ inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_nex
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 LIBPROTOBUF_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 fieldOrdinal);
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options* options);
-// Determines whether the given message is a map entry message, i.e. one implicitly created
-// by protoc due to a map<key, value> field.
+// 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();
}
-// 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.
+// 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";
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index 15c68b3f..565d1225 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -48,8 +48,9 @@ namespace compiler {
namespace csharp {
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ int fieldOrdinal,
+ const Options* options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
}
MapFieldGenerator::~MapFieldGenerator() {
@@ -62,8 +63,10 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
descriptor_->message_type()->FindFieldByName("value");
variables_["key_type_name"] = type_name(key_descriptor);
variables_["value_type_name"] = type_name(value_descriptor);
- scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1));
- scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+ scoped_ptr<FieldGeneratorBase> key_generator(
+ CreateFieldGenerator(key_descriptor, 1, this->options()));
+ scoped_ptr<FieldGeneratorBase> value_generator(
+ CreateFieldGenerator(value_descriptor, 2, this->options()));
printer->Print(
variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
index f33fe1c3..84a33a03 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -43,7 +43,9 @@ namespace csharp {
class MapFieldGenerator : public FieldGeneratorBase {
public:
- MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ MapFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options* options);
~MapFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index e0230a24..532da6b9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -60,8 +60,9 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
return d1->number() < d2->number();
}
-MessageGenerator::MessageGenerator(const Descriptor* descriptor)
- : SourceGeneratorBase(descriptor->file()),
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+ const Options* options)
+ : SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor) {
// sorted field names
@@ -185,7 +186,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
printer->Outdent();
printer->Print("}\n");
- // TODO: Should we put the oneof .proto comments here? It's unclear exactly where they should go.
+ // 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"
@@ -214,13 +216,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print("public static partial class Types {\n");
printer->Indent();
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- EnumGenerator enumGenerator(descriptor_->enum_type(i));
+ EnumGenerator 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));
+ MessageGenerator messageGenerator(
+ descriptor_->nested_type(i), this->options());
messageGenerator.Generate(printer);
}
}
@@ -268,7 +271,8 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
// Clone just the right field for each oneof
for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
- vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+ vars["property_name"] = UnderscoresToCamelCase(
+ descriptor_->oneof_decl(i)->name(), true);
printer->Print(vars, "switch (other.$property_name$Case) {\n");
printer->Indent();
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
@@ -449,7 +453,8 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
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 }.
+ // 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(
@@ -490,7 +495,7 @@ int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor) {
- return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
+ return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
}
} // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index f0c49ac9..f794d68d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -47,7 +47,7 @@ class FieldGeneratorBase;
class MessageGenerator : public SourceGeneratorBase {
public:
- MessageGenerator(const Descriptor* descriptor);
+ MessageGenerator(const Descriptor* descriptor, const Options* options);
~MessageGenerator();
void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index f81f769b..338692f8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -41,6 +41,7 @@
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
@@ -48,8 +49,9 @@ namespace compiler {
namespace csharp {
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ int fieldOrdinal,
+ const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
}
@@ -143,9 +145,11 @@ void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
"pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
}
-MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : MessageFieldGenerator(descriptor, fieldOrdinal) {
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options)
+ : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
SetCommonOneofFieldVariables(&variables_);
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index dc6e4dc5..7d614756 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -43,7 +43,9 @@ namespace csharp {
class MessageFieldGenerator : public FieldGeneratorBase {
public:
- MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~MessageFieldGenerator();
virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,7 +67,9 @@ class MessageFieldGenerator : public FieldGeneratorBase {
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
- MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~MessageOneofFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h
new file mode 100644
index 00000000..4079bf7f
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_options.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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+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),
+ legacy_enum_values(false) {
+ }
+ // Extension of the generated file. Defaults to ".cs"
+ 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.
+ 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;
+ // By default, C# codegen now uses PascalCased enum values names, after
+ // removing the enum type name as a prefix (if it *is* a prefix of the value).
+ // Setting this option reverts to the previous behavior of just copying the
+ // value name specified in the .proto file, allowing gradual migration.
+ // This option will be removed before final release.
+ bool legacy_enum_values;
+};
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index 60afd892..3b7ca75a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
namespace google {
@@ -48,8 +49,8 @@ namespace compiler {
namespace csharp {
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
// TODO(jonskeet): Make this cleaner...
is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
&& descriptor->type() != FieldDescriptor::TYPE_BYTES;
@@ -163,8 +164,8 @@ void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal)
- : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
SetCommonOneofFieldVariables(&variables_);
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index 8b87ebc4..5f466fc4 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -41,9 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
+struct Options;
+
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
- PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~PrimitiveFieldGenerator();
virtual void GenerateCodecCode(io::Printer* printer);
@@ -67,7 +71,9 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
- PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~PrimitiveOneofFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
index 22dae43b..f7397c0f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -43,6 +43,7 @@
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_message.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
namespace google {
@@ -50,8 +51,9 @@ namespace protobuf {
namespace compiler {
namespace csharp {
-ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file)
- : SourceGeneratorBase(file),
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
+ const Options* options)
+ : SourceGeneratorBase(file, options),
file_(file) {
namespace_ = GetFileNamespace(file);
reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
@@ -72,7 +74,7 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
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));
+ EnumGenerator enumGenerator(file_->enum_type(i), this->options());
enumGenerator.Generate(printer);
}
printer->Print("#endregion\n");
@@ -83,7 +85,7 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
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));
+ MessageGenerator messageGenerator(file_->message_type(i), this->options());
messageGenerator.Generate(printer);
}
printer->Print("#endregion\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
index 0a5b8ed5..e0c69f31 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
@@ -43,7 +43,7 @@ namespace csharp {
class ReflectionClassGenerator : public SourceGeneratorBase {
public:
- ReflectionClassGenerator(const FileDescriptor* file);
+ ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
~ReflectionClassGenerator();
void Generate(io::Printer* printer);
@@ -56,7 +56,9 @@ class ReflectionClassGenerator : public SourceGeneratorBase {
void WriteIntroduction(io::Printer* printer);
void WriteDescriptor(io::Printer* printer);
- void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
+ void WriteGeneratedCodeInfo(const Descriptor* descriptor,
+ io::Printer* printer,
+ bool last);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionClassGenerator);
};
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 3a11b75d..1befdc15 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index ee50eef0..819b5832 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -45,7 +45,9 @@ namespace csharp {
// should probably have a RepeatedFieldGeneratorBase.
class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
public:
- RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~RepeatedEnumFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index fc12faed..d51e638a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -49,8 +49,8 @@ namespace compiler {
namespace csharp {
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@@ -66,10 +66,12 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
// "create single field generator for this repeated field"
// function, but it doesn't seem worth it for just this.
if (IsWrapperType(descriptor_)) {
- scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_));
+ scoped_ptr<FieldGeneratorBase> single_generator(
+ new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
single_generator->GenerateCodecCode(printer);
} else {
- scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_));
+ scoped_ptr<FieldGeneratorBase> single_generator(
+ new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
single_generator->GenerateCodecCode(printer);
}
printer->Print(";\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index cf601c7e..6e33648b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -41,9 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
+struct Options;
+
class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
public:
- RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~RepeatedMessageFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index 5fe0b203..bee3f363 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index f1ceeb50..a59348a9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -43,7 +43,7 @@ namespace csharp {
class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
public:
- RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
~RepeatedPrimitiveFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
index 735d164a..16411e49 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -39,14 +39,17 @@
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace csharp {
-SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor)
- : descriptor_(descriptor) {
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
+ const Options *options)
+ : descriptor_(descriptor), options_(options) {
}
SourceGeneratorBase::~SourceGeneratorBase() {
@@ -57,7 +60,11 @@ void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
}
std::string SourceGeneratorBase::class_access_level() {
- return IsDescriptorProto(descriptor_) ? "internal" : "public"; // public_classes is always on.
+ return (IsDescriptorProto(descriptor_) || this->options()->internal_access) ? "internal" : "public";
+}
+
+const Options* SourceGeneratorBase::options() {
+ return this->options_;
}
} // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
index 6caef171..2e734581 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -40,17 +40,21 @@ namespace protobuf {
namespace compiler {
namespace csharp {
+struct Options;
+
class SourceGeneratorBase {
protected:
- SourceGeneratorBase(const FileDescriptor* descriptor);
+ SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
virtual ~SourceGeneratorBase();
std::string class_access_level();
+ const Options* options();
void WriteGeneratedCodeAttributes(io::Printer* printer);
private:
const FileDescriptor* descriptor_;
+ const Options *options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase);
};
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 6a3750e0..5cb86b6b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
namespace google {
@@ -47,8 +48,8 @@ namespace compiler {
namespace csharp {
WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : FieldGeneratorBase(descriptor, fieldOrdinal) {
+ int fieldOrdinal, const Options *options)
+ : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@@ -151,9 +152,9 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
}
-WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal)
- : WrapperFieldGenerator(descriptor, fieldOrdinal) {
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+ : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
SetCommonOneofFieldVariables(&variables_);
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index 6e2414af..250dfd25 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -41,9 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
+struct Options;
+
class WrapperFieldGenerator : public FieldGeneratorBase {
public:
- WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ WrapperFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~WrapperFieldGenerator();
virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,7 +69,9 @@ class WrapperFieldGenerator : public FieldGeneratorBase {
class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
public:
- WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+ WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+ int fieldOrdinal,
+ const Options *options);
~WrapperOneofFieldGenerator();
virtual void GenerateMembers(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index be19aa2e..1b6e9700 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -32,25 +32,26 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/importer.h>
+
#include <google/protobuf/stubs/hash.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/map_util.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index 7d21fe61..0a112888 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -43,7 +43,7 @@ namespace compiler {
namespace java {
Context::Context(const FileDescriptor* file)
- : name_resolver_(new ClassNameResolver) {
+ : name_resolver_(new ClassNameResolver), enforce_lite_(false) {
InitializeFieldGeneratorInfo(file);
}
@@ -189,6 +189,13 @@ const OneofGeneratorInfo* Context::GetOneofGeneratorInfo(
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 enforce_lite_ || descriptor->file()->options().optimize_for() !=
+ FileOptions::CODE_SIZE;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index 5b595d07..a480e45d 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -46,6 +46,7 @@ namespace protobuf {
class FieldDescriptor;
class OneofDescriptor;
class Descriptor;
+ class EnumDescriptor;
namespace compiler {
namespace java {
class ClassNameResolver; // name_resolver.h
@@ -78,6 +79,20 @@ class Context {
const OneofGeneratorInfo* GetOneofGeneratorInfo(
const OneofDescriptor* oneof) const;
+ // Enforces all the files (including transitive dependencies) to use
+ // LiteRuntime.
+ void SetEnforceLite(bool enforce_lite) {
+ enforce_lite_ = enforce_lite;
+ }
+
+ bool EnforceLite() const {
+ return 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);
@@ -87,6 +102,7 @@ class Context {
google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
+ bool enforce_lite_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
};
diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc
index 663f0c97..0b5caba4 100644
--- a/src/google/protobuf/compiler/java/java_doc_comment.cc
+++ b/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -120,9 +120,7 @@ static void WriteDocCommentBodyForLocation(
lines.pop_back();
}
- printer->Print(
- " *\n"
- " * <pre>\n");
+ 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
@@ -133,7 +131,9 @@ static void WriteDocCommentBodyForLocation(
printer->Print(" *$line$\n", "line", lines[i]);
}
}
- printer->Print(" * </pre>\n");
+ printer->Print(
+ " * </pre>\n"
+ " *\n");
}
}
@@ -163,12 +163,12 @@ static string FirstLineOf(const string& value) {
}
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, message);
printer->Print(
- "/**\n"
- " * Protobuf type {@code $fullname$}\n",
+ " * Protobuf type {@code $fullname$}\n"
+ " */\n",
"fullname", EscapeJavadoc(message->full_name()));
- WriteDocCommentBody(printer, message);
- printer->Print(" */\n");
}
void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
@@ -176,55 +176,55 @@ void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
// etc., but in practice everyone already knows the difference between these
// so it's redundant information.
- // We use the field declaration as the first line of the comment, e.g.:
+ // 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;
- // This communicates a lot of information about the field in a small space.
// If the field is a group, the debug string might end with {.
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, field);
printer->Print(
- "/**\n"
" * <code>$def$</code>\n",
"def", EscapeJavadoc(FirstLineOf(field->DebugString())));
- WriteDocCommentBody(printer, field);
printer->Print(" */\n");
}
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, enum_);
printer->Print(
- "/**\n"
- " * Protobuf enum {@code $fullname$}\n",
+ " * Protobuf enum {@code $fullname$}\n"
+ " */\n",
"fullname", EscapeJavadoc(enum_->full_name()));
- WriteDocCommentBody(printer, enum_);
- printer->Print(" */\n");
}
void WriteEnumValueDocComment(io::Printer* printer,
const EnumValueDescriptor* value) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, value);
printer->Print(
- "/**\n"
- " * <code>$def$</code>\n",
+ " * <code>$def$</code>\n"
+ " */\n",
"def", EscapeJavadoc(FirstLineOf(value->DebugString())));
- WriteDocCommentBody(printer, value);
- printer->Print(" */\n");
}
void WriteServiceDocComment(io::Printer* printer,
const ServiceDescriptor* service) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, service);
printer->Print(
- "/**\n"
- " * Protobuf service {@code $fullname$}\n",
+ " * Protobuf service {@code $fullname$}\n"
+ " */\n",
"fullname", EscapeJavadoc(service->full_name()));
- WriteDocCommentBody(printer, service);
- printer->Print(" */\n");
}
void WriteMethodDocComment(io::Printer* printer,
const MethodDescriptor* method) {
+ printer->Print("/**\n");
+ WriteDocCommentBody(printer, method);
printer->Print(
- "/**\n"
- " * <code>$def$</code>\n",
+ " * <code>$def$</code>\n"
+ " */\n",
"def", EscapeJavadoc(FirstLineOf(method->DebugString())));
- WriteDocCommentBody(printer, method);
- printer->Print(" */\n");
}
} // namespace java
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 5fc9b002..947b80e4 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -64,6 +64,7 @@ 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);
@@ -91,6 +92,16 @@ void EnumGenerator::Generate(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
+ bool ordinal_is_index = true;
+ 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++) {
map<string, string> vars;
vars["name"] = canonical_values_[i]->name();
@@ -100,12 +111,21 @@ void EnumGenerator::Generate(io::Printer* printer) {
if (canonical_values_[i]->options().deprecated()) {
printer->Print("@java.lang.Deprecated\n");
}
- printer->Print(vars,
- "$name$($index$, $number$),\n");
+ if (ordinal_is_index) {
+ printer->Print(vars,
+ "$name$($number$),\n");
+ } else {
+ printer->Print(vars,
+ "$name$($index$, $number$),\n");
+ }
}
if (SupportUnknownEnumValue(descriptor_->file())) {
- printer->Print("UNRECOGNIZED(-1, -1),\n");
+ if (ordinal_is_index) {
+ printer->Print("UNRECOGNIZED(-1),\n");
+ } else {
+ printer->Print("UNRECOGNIZED(-1, -1),\n");
+ }
}
printer->Print(
@@ -140,17 +160,33 @@ void EnumGenerator::Generate(io::Printer* printer) {
"\n"
"public final int getNumber() {\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
- printer->Print(
- " if (index == -1) {\n"
- " throw new java.lang.IllegalArgumentException(\n"
- " \"Can't get the number of an unknown enum value.\");\n"
- " }\n");
+ 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"
+ " * @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();
@@ -178,7 +214,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
" $classname$> internalValueMap =\n"
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
" public $classname$ findValueByNumber(int number) {\n"
- " return $classname$.valueOf(number);\n"
+ " return $classname$.forNumber(number);\n"
" }\n"
" };\n"
"\n",
@@ -187,18 +223,19 @@ void EnumGenerator::Generate(io::Printer* printer) {
// -----------------------------------------------------------------
// Reflection
- if (HasDescriptorMethods(descriptor_)) {
+ if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
printer->Print(
"public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
" getValueDescriptor() {\n"
- " return getDescriptor().getValues().get(index);\n"
+ " 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");
+ " 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
@@ -229,7 +266,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
" (com.google.protobuf.Descriptors.FileDescriptor)\n"
" m.invoke(immutableFileClass);\n"
" return file.getEnumTypes().get($index$);\n"
- "} catch (Exception e) {\n"
+ "} catch (java.lang.Exception e) {\n"
// Immutable classes cannot be found. Proceed as if custom options
// don't exist.
"}\n",
@@ -304,16 +341,27 @@ void EnumGenerator::Generate(io::Printer* printer) {
"}\n"
"\n");
- printer->Print("private final int index;\n");
+ if (!ordinal_is_index) {
+ printer->Print("private final int index;\n");
+ }
}
// -----------------------------------------------------------------
printer->Print(
- "private final int value;\n\n"
- "private $classname$(int index, int value) {\n",
- "classname", descriptor_->name());
- if (HasDescriptorMethods(descriptor_)) {
+ "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(
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 558da968..3e54be3d 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -68,21 +68,14 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_number"] = SimpleItoa(
descriptor->default_value_enum()->number());
- if (descriptor->is_packed()) {
- (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag(
- descriptor->number(),
- internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
- } else {
- (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
- }
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+ (*variables)["on_changed"] = "onChanged();";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -198,7 +191,7 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " $type$ result = $type$.valueOf($name$_);\n"
+ " $type$ result = $type$.forNumber($name$_);\n"
" return result == null ? $unknown$ : result;\n"
"}\n");
}
@@ -231,7 +224,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " $type$ result = $type$.valueOf($name$_);\n"
+ " $type$ result = $type$.forNumber($name$_);\n"
" return result == null ? $unknown$ : result;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -311,7 +304,7 @@ GenerateParsingCode(io::Printer* printer) const {
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -405,7 +398,7 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
@@ -443,7 +436,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
@@ -500,7 +493,7 @@ GenerateParsingCode(io::Printer* printer) const {
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -613,7 +606,7 @@ GenerateMembers(io::Printer* printer) const {
" new com.google.protobuf.Internal.ListAdapter.Converter<\n"
" java.lang.Integer, $type$>() {\n"
" public $type$ convert(java.lang.Integer from) {\n"
- " $type$ result = $type$.valueOf(from);\n"
+ " $type$ result = $type$.forNumber(from);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" };\n");
@@ -649,7 +642,7 @@ GenerateMembers(io::Printer* printer) const {
}
if (descriptor_->is_packed() &&
- HasGeneratedMethods(descriptor_->containing_type())) {
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
}
@@ -846,7 +839,7 @@ GenerateParsingCode(io::Printer* printer) const {
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index e3e87c58..908d6db4 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -75,8 +75,6 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -179,7 +177,7 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " $type$ result = $type$.valueOf($name$_);\n"
+ " $type$ result = $type$.forNumber($name$_);\n"
" return result == null ? $unknown$ : result;\n"
"}\n");
@@ -228,7 +226,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
" copyOnWrite();\n"
- " instance.set$capitalized_name$Value(int value);\n"
+ " instance.set$capitalized_name$Value(value);\n"
" return this;\n"
"}\n");
}
@@ -264,17 +262,15 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void ImmutableEnumFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n"
+ " other.has$capitalized_name$(), other.$name$_);\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");
+ "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_,"
+ " other.$name$_ != $default_number$, other.$name$_);\n");
} else {
GOOGLE_LOG(FATAL) << "Can't reach here.";
}
@@ -295,7 +291,7 @@ GenerateParsingCode(io::Printer* printer) const {
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -389,7 +385,7 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
@@ -468,14 +464,10 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void ImmutableEnumOneofFieldLiteGenerator::
-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");
- }
+GenerateVisitCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$oneof_name$_ = visitor.visitOneofInt(\n"
+ " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
}
void ImmutableEnumOneofFieldLiteGenerator::
@@ -488,7 +480,7 @@ GenerateParsingCode(io::Printer* printer) const {
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
"if (value == null) {\n");
if (PreserveUnknownFields(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -602,7 +594,7 @@ GenerateMembers(io::Printer* printer) const {
" new com.google.protobuf.Internal.ListAdapter.Converter<\n"
" java.lang.Integer, $type$>() {\n"
" public $type$ convert(java.lang.Integer from) {\n"
- " $type$ result = $type$.valueOf(from);\n"
+ " $type$ result = $type$.forNumber(from);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" };\n");
@@ -638,7 +630,7 @@ GenerateMembers(io::Printer* printer) const {
}
if (descriptor_->options().packed() &&
- HasGeneratedMethods(descriptor_->containing_type())) {
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
}
@@ -647,7 +639,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = newIntList($name$_);\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
" }\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -807,22 +800,9 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void RepeatedImmutableEnumFieldLiteGenerator::
-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"
- " } else {\n"
- " ensure$capitalized_name$IsMutable();\n"
- " $name$_.addAll(other.$name$_);\n"
- " }\n"
- " $on_changed$\n"
- "}\n");
+GenerateVisitCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_= visitor.visitIntList($name$_, other.$name$_);\n");
}
void RepeatedImmutableEnumFieldLiteGenerator::
@@ -834,27 +814,23 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
// Read and store the enum
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+ "}\n");
+
if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- "int rawValue = input.readEnum();\n"
- "if (!$is_mutable$) {\n"
- " $name$_ = newIntList();\n"
- "}\n"
- "$name$_.addInt(rawValue);\n");
+ "$name$_.addInt(input.readEnum());\n");
} else {
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
- "if (value == null) {\n");
- if (PreserveUnknownFields(descriptor_->containing_type())) {
- printer->Print(variables_,
- " super.mergeVarintField($number$, rawValue);\n");
- }
- printer->Print(variables_,
+ "$type$ value = $type$.forNumber(rawValue);\n"
+ "if (value == null) {\n"
+ // We store the unknown value in unknown fields.
+ " super.mergeVarintField($number$, rawValue);\n"
"} else {\n"
- " if (!$is_mutable$) {\n"
- " $name$_ = newIntList();\n"
- " }\n"
" $name$_.addInt(rawValue);\n"
"}\n");
}
@@ -862,7 +838,11 @@ GenerateParsingCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldLiteGenerator::
GenerateParsingCodeFromPacked(io::Printer* printer) const {
- // Wrap GenerateParsingCode's contents with a while loop.
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+ "}\n");
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
@@ -870,7 +850,21 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
"while(input.getBytesUntilLimit() > 0) {\n");
printer->Indent();
- GenerateParsingCode(printer);
+ // Read and store the enum
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "$name$_.addInt(input.readEnum());\n");
+ } else {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.forNumber(rawValue);\n"
+ "if (value == null) {\n"
+ // We store the unknown value in unknown fields.
+ " super.mergeVarintField($number$, rawValue);\n"
+ "} else {\n"
+ " $name$_.addInt(rawValue);\n"
+ "}\n");
+ }
printer->Outdent();
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
index 2c41c3e4..9201b8d6 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -67,7 +67,7 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -101,7 +101,7 @@ class ImmutableEnumOneofFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -127,7 +127,7 @@ class RepeatedImmutableEnumFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index ed415eee..c22da8d7 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -141,7 +141,15 @@ void EnumLiteGenerator::Generate(io::Printer* printer) {
" return value;\n"
"}\n"
"\n"
+ "/**\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();
@@ -169,7 +177,7 @@ void EnumLiteGenerator::Generate(io::Printer* printer) {
" $classname$> internalValueMap =\n"
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
" public $classname$ findValueByNumber(int number) {\n"
- " return $classname$.valueOf(number);\n"
+ " return $classname$.forNumber(number);\n"
" }\n"
" };\n"
"\n",
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4db7085e..46b5faaa 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -118,75 +118,38 @@ void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
"public static final int $constant_name$ = $number$;\n");
WriteFieldDocComment(printer, descriptor_);
- if (HasDescriptorMethods(descriptor_->file())) {
- // Non-lite extensions
- if (descriptor_->extension_scope() == NULL) {
- // Non-nested
- printer->Print(
- vars,
- "public static final\n"
- " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
- " $containing_type$,\n"
- " $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
- " .newFileScopedGeneratedExtension(\n"
- " $singular_type$.class,\n"
- " $prototype$);\n");
- } else {
- // Nested
- printer->Print(
- vars,
- "public static final\n"
- " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
- " $containing_type$,\n"
- " $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
- " .newMessageScopedGeneratedExtension(\n"
- " $scope$.getDefaultInstance(),\n"
- " $index$,\n"
- " $singular_type$.class,\n"
- " $prototype$);\n");
- }
+ 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 {
- // Lite extensions
- if (descriptor_->is_repeated()) {
- printer->Print(
- vars,
- "public static final\n"
- " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
- " $containing_type$,\n"
- " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
- " .newRepeatedGeneratedExtension(\n"
- " $containing_type$.getDefaultInstance(),\n"
- " $prototype$,\n"
- " $enum_map$,\n"
- " $number$,\n"
- " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
- " $packed$,\n"
- " $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");
- }
+ // 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");
}
}
int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
io::Printer* printer) {
int bytecode_estimate = 0;
- if (descriptor_->extension_scope() == NULL &&
- HasDescriptorMethods(descriptor_->file())) {
- // Only applies to non-nested, non-lite extensions.
+ if (descriptor_->extension_scope() == NULL) {
+ // Only applies to non-nested extensions.
printer->Print(
"$name$.internalInit(descriptor.getExtensions().get($index$));\n",
"name", UnderscoresToCamelCase(descriptor_),
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc
index e69de29b..23261bac 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.cc
+++ b/src/google/protobuf/compiler/java/java_extension_lite.cc
@@ -0,0 +1,118 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
+ const FieldDescriptor* descriptor, Context* context)
+ : descriptor_(descriptor), context_(context),
+ 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) {
+ map<string, 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");
+ }
+}
+
+int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode(
+ io::Printer* printer) {
+ return 0;
+}
+
+int ImmutableExtensionLiteGenerator::GenerateRegistrationCode(
+ io::Printer* printer) {
+ printer->Print(
+ "registry.add($scope$.$name$);\n",
+ "scope", scope_,
+ "name", UnderscoresToCamelCase(descriptor_));
+ return 7;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
index e69de29b..4cd49bda 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.h
+++ b/src/google/protobuf/compiler/java/java_extension_lite.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_JAVA_EXTENSION_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/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();
+
+ virtual void Generate(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateRegistrationCode(io::Printer* printer);
+
+ private:
+ const FieldDescriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ 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/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index c5434767..3c7bc5c4 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -77,7 +77,7 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
return new ImmutableMapFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new RepeatedImmutableLazyMessageFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
@@ -99,7 +99,7 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
if (field->containing_oneof()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new ImmutableLazyMessageOneofFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
@@ -119,7 +119,7 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
} else {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new ImmutableLazyMessageFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
@@ -150,7 +150,7 @@ ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
return new ImmutableMapFieldLiteGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new RepeatedImmutableLazyMessageFieldLiteGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
@@ -172,7 +172,7 @@ ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
if (field->containing_oneof()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new ImmutableLazyMessageOneofFieldLiteGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
@@ -192,7 +192,7 @@ ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
} else {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
+ if (IsLazy(field, context->EnforceLite())) {
return new ImmutableLazyMessageFieldLiteGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 0e24da24..4dd4f57f 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -105,7 +105,7 @@ class ImmutableFieldLiteGenerator {
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 GenerateMergingCode(io::Printer* printer) const = 0;
+ virtual void GenerateVisitCode(io::Printer* printer) const = 0;
virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer)
const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index c8172330..c53aae6b 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -177,7 +177,7 @@ void MaybeRestartJavaMethod(io::Printer* printer,
// since otherwise we hit a hardcoded limit in the jvm and javac will
// then fail with the error "code too large". This limit lets our
// estimates be off by a factor of two and still we're okay.
- static const int bytesPerMethod = 1<<15; // aka 32K
+ static const int bytesPerMethod = kMaxStaticSize;
if ((*bytecode_estimate) > bytesPerMethod) {
++(*method_num);
@@ -193,7 +193,8 @@ void MaybeRestartJavaMethod(io::Printer* printer,
} // namespace
-FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
+FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api,
+ bool enforce_lite)
: file_(file),
java_package_(FileJavaPackage(file, immutable_api)),
message_generators_(
@@ -204,6 +205,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
name_resolver_(context_->GetNameResolver()),
immutable_api_(immutable_api) {
classname_ = name_resolver_->GetFileClassName(file, immutable_api);
+ context_->SetEnforceLite(enforce_lite);
generator_factory_.reset(
new ImmutableGeneratorFactory(context_.get()));
for (int i = 0; i < file_->message_type_count(); ++i) {
@@ -262,7 +264,8 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Print(
"public static void registerAllExtensions(\n"
" com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
- "lite", HasDescriptorMethods(file_) ? "" : "Lite");
+ "lite",
+ HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite");
printer->Indent();
@@ -282,7 +285,7 @@ void FileGenerator::Generate(io::Printer* printer) {
if (!MultipleJavaFiles(file_, immutable_api_)) {
for (int i = 0; i < file_->enum_type_count(); i++) {
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
.Generate(printer);
} else {
@@ -294,7 +297,7 @@ void FileGenerator::Generate(io::Printer* printer) {
message_generators_[i]->GenerateInterface(printer);
message_generators_[i]->Generate(printer);
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, context_->EnforceLite())) {
for (int i = 0; i < file_->service_count(); i++) {
google::protobuf::scoped_ptr<ServiceGenerator> generator(
generator_factory_->NewServiceGenerator(file_->service(i)));
@@ -309,14 +312,18 @@ void FileGenerator::Generate(io::Printer* printer) {
extension_generators_[i]->Generate(printer);
}
- // Static variables.
+ // 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);
+ message_generators_[i]->GenerateStaticVariables(
+ printer, &static_block_bytecode_estimate);
}
printer->Print("\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
if (immutable_api_) {
GenerateDescriptorInitializationCodeForImmutable(printer);
} else {
@@ -358,9 +365,11 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
" getDescriptor() {\n"
" return descriptor;\n"
"}\n"
- "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+ "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
" descriptor;\n"
- "static {\n");
+ "static {\n",
+ // TODO(dweis): Mark this as final.
+ "final", "");
printer->Indent();
SharedCodeGenerator shared_code_generator(file_);
@@ -453,7 +462,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer*
" getDescriptor() {\n"
" return descriptor;\n"
"}\n"
- "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+ "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
" descriptor;\n"
"static {\n");
printer->Indent();
@@ -549,7 +558,7 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
vector<string>* file_list) {
if (MultipleJavaFiles(file_, immutable_api_)) {
for (int i = 0; i < file_->enum_type_count(); i++) {
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, context_->EnforceLite())) {
EnumGenerator generator(file_->enum_type(i), immutable_api_,
context_.get());
GenerateSibling<EnumGenerator>(package_dir, java_package_,
@@ -582,7 +591,7 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
message_generators_[i].get(),
&MessageGenerator::Generate);
}
- if (HasGenericServices(file_)) {
+ if (HasGenericServices(file_, context_->EnforceLite())) {
for (int i = 0; i < file_->service_count(); i++) {
google::protobuf::scoped_ptr<ServiceGenerator> generator(
generator_factory_->NewServiceGenerator(file_->service(i)));
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index 080b3424..7dbeb94e 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -67,7 +67,8 @@ namespace java {
class FileGenerator {
public:
- FileGenerator(const FileDescriptor* file, bool immutable_api = true);
+ FileGenerator(const FileDescriptor* file, bool immutable_api = true,
+ bool enforce_lite = false);
~FileGenerator();
// Checks for problems that would otherwise lead to cryptic compile errors.
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 6c6f7286..a46c7fc4 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -75,6 +75,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
bool generate_immutable_code = false;
bool generate_mutable_code = false;
bool generate_shared_code = false;
+ bool enforce_lite = false;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "output_list_file") {
output_list_file = options[i].second;
@@ -84,12 +85,21 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
generate_mutable_code = true;
} else if (options[i].first == "shared") {
generate_shared_code = true;
+ } else if (options[i].first == "lite") {
+ // When set, the protoc will generate the current files and all the
+ // transitive dependencies as lite runtime.
+ enforce_lite = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
+ if (enforce_lite && 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 (!generate_immutable_code && !generate_mutable_code &&
!generate_shared_code) {
@@ -105,10 +115,12 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
vector<FileGenerator*> file_generators;
if (generate_immutable_code) {
- file_generators.push_back(new FileGenerator(file, /* immutable = */ true));
+ file_generators.push_back(
+ new FileGenerator(file, /* immutable = */ true, enforce_lite));
}
if (generate_mutable_code) {
- file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+ file_generators.push_back(
+ new FileGenerator(file, /* mutable = */ false, enforce_lite));
}
for (int i = 0; i < file_generators.size(); ++i) {
if (!file_generators[i]->Validate(error)) {
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
index 92ef851b..3218b410 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.cc
+++ b/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
#include <google/protobuf/compiler/java/java_field.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_message.h>
@@ -58,17 +59,20 @@ ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {}
MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
const Descriptor* descriptor) const {
- if (descriptor->file()->options().optimize_for() ==
- FileOptions::LITE_RUNTIME) {
- return new ImmutableMessageLiteGenerator(descriptor, context_);
- } else {
+ if (HasDescriptorMethods(descriptor, context_->EnforceLite())) {
return new ImmutableMessageGenerator(descriptor, context_);
+ } else {
+ return new ImmutableMessageLiteGenerator(descriptor, context_);
}
}
ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
const FieldDescriptor* descriptor) const {
- return new ImmutableExtensionGenerator(descriptor, context_);
+ if (HasDescriptorMethods(descriptor->file(), context_->EnforceLite())) {
+ return new ImmutableExtensionGenerator(descriptor, context_);
+ } else {
+ return new ImmutableExtensionLiteGenerator(descriptor, context_);
+ }
}
ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 5392d6d7..c850423e 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -170,44 +170,41 @@ inline string ImmutableDefaultValue(const FieldDescriptor* field,
}
bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
-// Does this message class have generated parsing, serialization, and other
-// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const Descriptor* descriptor) {
- return descriptor->file()->options().optimize_for() !=
- FileOptions::CODE_SIZE;
-}
-
// Does this message have specialized equals() and hashCode() methods?
inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
return descriptor->file()->options().java_generate_equals_and_hash();
}
// Does this message class have descriptor and reflection methods?
-inline bool HasDescriptorMethods(const Descriptor* descriptor) {
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const Descriptor* descriptor,
+ bool enforce_lite) {
+ return !enforce_lite &&
+ descriptor->file()->options().optimize_for() !=
+ FileOptions::LITE_RUNTIME;
}
-inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor,
+ bool enforce_lite) {
+ return !enforce_lite &&
+ descriptor->file()->options().optimize_for() !=
+ FileOptions::LITE_RUNTIME;
}
-inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
- return descriptor->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor,
+ bool enforce_lite) {
+ return !enforce_lite &&
+ descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) {
return file->service_count() > 0 &&
- file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ HasDescriptorMethods(file, enforce_lite) &&
file->options().java_generic_services();
}
-inline bool IsLazy(const FieldDescriptor* descriptor) {
+inline bool IsLazy(const FieldDescriptor* descriptor, bool enforce_lite) {
// Currently, the proto-lite version suports lazy field.
// TODO(niwasaki): Support lazy fields also for other proto runtimes.
- if (descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME) {
+ if (HasDescriptorMethods(descriptor->file(), enforce_lite)) {
return false;
}
return descriptor->options().lazy();
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
index 283ba1d3..62f39302 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -182,18 +182,17 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void ImmutableLazyMessageFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " $name$_.merge(other.$name$_);\n"
- " $set_has_field_bit_message$;\n"
- "}\n");
+ "$name$_ = visitor.visitLazyMessage(\n"
+ " has$capitalized_name$(), $name$_,\n"
+ " other.has$capitalized_name$(), other.$name$_);\n");
}
void ImmutableLazyMessageFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+ "$name$_.mergeFrom(input, extensionRegistry);\n");
printer->Print(variables_,
"$set_has_field_bit_message$;\n");
}
@@ -362,14 +361,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void ImmutableLazyMessageOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "if (!($has_oneof_case_message$)) {\n"
- " $oneof_name$_ = new $lazy_type$();\n"
- "}\n"
- "(($lazy_type$) $oneof_name$_).merge(\n"
- " ($lazy_type$) other.$oneof_name$_);\n"
- "$set_oneof_case_message$;\n");
+ "$oneof_name$_ = visitor.visitOneofLazyMessage(\n"
+ " $has_oneof_case_message$,\n"
+ " ($lazy_type$) $oneof_name$_,\n"
+ " ($lazy_type$) other.$oneof_name$_);\n");
}
void ImmutableLazyMessageOneofFieldLiteGenerator::
@@ -378,8 +375,7 @@ GenerateParsingCode(io::Printer* printer) const {
"if (!($has_oneof_case_message$)) {\n"
" $oneof_name$_ = new $lazy_type$();\n"
"}\n"
- "(($lazy_type$) $oneof_name$_).setByteString(\n"
- " input.readBytes(), extensionRegistry);\n"
+ "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n"
"$set_oneof_case_message$;\n");
}
@@ -464,7 +460,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = newProtobufList($name$_);\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
" }\n"
"}\n"
"\n");
@@ -679,7 +676,8 @@ void RepeatedImmutableLazyMessageFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = newProtobufList();\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
"}\n"
"$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
" extensionRegistry, input.readBytes()));\n");
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
index e85ec0f3..47ebeb49 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
@@ -63,7 +63,7 @@ class ImmutableLazyMessageFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -82,7 +82,7 @@ class ImmutableLazyMessageOneofFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 3e035c89..2a551ca4 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -79,9 +79,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
const FieldGeneratorInfo* info,
- ClassNameResolver* name_resolver,
+ Context* context,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, info, variables);
+ ClassNameResolver* name_resolver = context->GetNameResolver();
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->message_type());
@@ -123,8 +124,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+ (*variables)["on_changed"] = "onChanged();";
// For repeated fields, one bit is used for whether the array is immutable
// in the parsing constructor.
@@ -135,18 +135,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["default_entry"] = (*variables)["capitalized_name"] +
"DefaultEntryHolder.defaultEntry";
- if (HasDescriptorMethods(descriptor->file())) {
- (*variables)["lite"] = "";
- (*variables)["map_field_parameter"] = (*variables)["default_entry"];
- (*variables)["descriptor"] =
- name_resolver->GetImmutableClassName(descriptor->file()) +
- ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
- "_descriptor, ";
- } else {
- (*variables)["lite"] = "Lite";
- (*variables)["map_field_parameter"] = "";
- (*variables)["descriptor"] = "";
- }
+ (*variables)["lite"] = "";
+ (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+ (*variables)["descriptor"] =
+ name_resolver->GetImmutableClassName(descriptor->file()) +
+ ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+ "_descriptor, ";
}
} // namespace
@@ -159,7 +153,7 @@ ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor),
- name_resolver_, &variables_);
+ context, &variables_);
}
ImmutableMapFieldGenerator::
@@ -221,7 +215,7 @@ GenerateMembers(io::Printer* printer) const {
" if ($name$_ == null) {\n"
" return com.google.protobuf.MapField$lite$.emptyMapField(\n"
" $map_field_parameter$);\n"
- " }\n"
+ " }\n"
" return $name$_;\n"
"}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
@@ -276,7 +270,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" if ($name$_ == null) {\n"
" return com.google.protobuf.MapField$lite$.emptyMapField(\n"
" $map_field_parameter$);\n"
- " }\n"
+ " }\n"
" return $name$_;\n"
"}\n"
"private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
@@ -424,7 +418,7 @@ GenerateParsingCode(io::Printer* printer) const {
"$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
printer->Print(
variables_,
- "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+ "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
" unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
" $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index d2039403..b80d4139 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -79,10 +79,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
const FieldGeneratorInfo* info,
- ClassNameResolver* name_resolver,
+ Context* context,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, info, variables);
+ ClassNameResolver* name_resolver = context->GetNameResolver();
(*variables)["type"] =
name_resolver->GetImmutableClassName(descriptor->message_type());
const FieldDescriptor* key = KeyField(descriptor);
@@ -123,8 +124,6 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
(*variables)["default_entry"] = (*variables)["capitalized_name"] +
"DefaultEntryHolder.defaultEntry";
@@ -142,7 +141,7 @@ ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor,
: descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
context->GetFieldGeneratorInfo(descriptor),
- name_resolver_, &variables_);
+ context, &variables_);
}
ImmutableMapFieldLiteGenerator::
@@ -375,10 +374,10 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void ImmutableMapFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(
variables_,
- "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ "$name$_ = visitor.visitMap(internalGetMutable$capitalized_name$(),\n"
" other.internalGet$capitalized_name$());\n");
}
@@ -404,7 +403,7 @@ GenerateParsingCode(io::Printer* printer) const {
"$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
printer->Print(
variables_,
- "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+ "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
" super.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
" $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
index a09cd536..555b5c5b 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -52,7 +52,7 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 22a70c32..4c474a48 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -89,19 +89,20 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor)
MessageGenerator::~MessageGenerator() {}
// ===================================================================
-// TODO(api): Move this class to a separate immutable_message.cc file.
ImmutableMessageGenerator::ImmutableMessageGenerator(
const Descriptor* descriptor, Context* context)
: MessageGenerator(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
- GOOGLE_CHECK_NE(
- FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+ 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) {
+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
@@ -124,23 +125,29 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
} 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 com.google.protobuf.Descriptors.Descriptor\n"
+ "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
" internal_$identifier$_descriptor;\n");
+ *bytecode_estimate += 30;
// And the FieldAccessorTable.
- GenerateFieldAccessorTable(printer);
+ 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);
+ .GenerateStaticVariables(printer, bytecode_estimate);
}
}
@@ -183,7 +190,7 @@ int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
}
void ImmutableMessageGenerator::
-GenerateFieldAccessorTable(io::Printer* printer) {
+GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
map<string, string> vars;
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
@@ -193,10 +200,19 @@ GenerateFieldAccessorTable(io::Printer* printer) {
} else {
vars["private"] = "private ";
}
+ if (*bytecode_estimate <= kMaxStaticSize) {
+ vars["final"] = "final ";
+ } else {
+ vars["final"] = "";
+ }
printer->Print(vars,
- "$private$static\n"
+ "$private$static $final$\n"
" com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
" internal_$identifier$_fieldAccessorTable;\n");
+
+ // 6 bytes per field and oneof
+ *bytecode_estimate += 10 + 6 * descriptor_->field_count()
+ + 6 * descriptor_->oneof_decl_count();
}
int ImmutableMessageGenerator::
@@ -342,7 +358,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print(
"}\n");
- if (HasGeneratedMethods(descriptor_)) {
+ if (context_->HasGeneratedMethods(descriptor_)) {
GenerateParsingConstructor(printer);
}
@@ -408,12 +424,20 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"cap_oneof_name",
ToUpper(vars["oneof_name"]));
printer->Print(vars,
- "private int value = 0;\n"
+ "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 < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -426,8 +450,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
}
printer->Print(
" case 0: return $cap_oneof_name$_NOT_SET;\n"
- " default: throw new java.lang.IllegalArgumentException(\n"
- " \"Value is undefined for this oneof enum.\");\n"
+ " default: return null;\n"
" }\n"
"}\n"
"public int getNumber() {\n"
@@ -440,7 +463,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print(vars,
"public $oneof_capitalized_name$Case\n"
"get$oneof_capitalized_name$Case() {\n"
- " return $oneof_capitalized_name$Case.valueOf(\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
" $oneof_name$Case_);\n"
"}\n"
"\n");
@@ -459,7 +482,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
- if (HasGeneratedMethods(descriptor_)) {
+ if (context_->HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
}
@@ -664,34 +687,40 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+ " return com.google.protobuf.GeneratedMessage\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.parseWithIOException(PARSER, input, extensionRegistry);"
+ " return com.google.protobuf.GeneratedMessage\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.parseDelimitedWithIOException(PARSER, input);"
+ " return com.google.protobuf.GeneratedMessage\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.parseDelimitedWithIOException(PARSER, input, extensionRegistry);"
+ " return com.google.protobuf.GeneratedMessage\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.parseWithIOException(PARSER, input);"
+ " return com.google.protobuf.GeneratedMessage\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.parseWithIOException(PARSER, input, extensionRegistry);"
+ " return com.google.protobuf.GeneratedMessage\n"
+ " .parseWithIOException(PARSER, input, extensionRegistry);\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -1049,22 +1078,52 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+ // hashCode non-oneofs.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
- if (check_has_bits) {
+ if (field->containing_oneof() == NULL) {
+ 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 (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "switch ($oneof_name$Case_) {\n",
+ "oneof_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "if (has$name$()) {\n",
- "name", info->capitalized_name);
+ "case $field_number$:\n",
+ "field_number",
+ SimpleItoa(field->number()));
printer->Indent();
- }
- field_generators_.get(field).GenerateHashCode(printer);
- if (check_has_bits) {
+ field_generators_.get(field).GenerateHashCode(printer);
+ printer->Print("break;\n");
printer->Outdent();
- printer->Print("}\n");
}
+ 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");
@@ -1105,7 +1164,8 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print(
"private $classname$(\n"
" com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n",
"classname", descriptor_->name());
printer->Indent();
@@ -1165,7 +1225,8 @@ GenerateParsingConstructor(io::Printer* printer) {
"default: {\n"
" if (!input.skipField(tag)) {\n"
" done = true;\n" // it's an endgroup tag
- " }\n"
+ " }\n");
+ printer->Print(
" break;\n"
"}\n");
}
@@ -1215,10 +1276,10 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Outdent();
printer->Print(
"} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+ " throw e.setUnfinishedMessage(this);\n"
"} catch (java.io.IOException e) {\n"
- " throw new RuntimeException(new com.google.protobuf.InvalidProtocolBufferException(e)\n"
- " .setUnfinishedMessage(this));\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e).setUnfinishedMessage(this);\n"
"} finally {\n");
printer->Indent();
@@ -1260,20 +1321,9 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n",
"classname", descriptor_->name());
- if (HasGeneratedMethods(descriptor_)) {
- // The parsing constructor throws an InvalidProtocolBufferException via a
- // RuntimeException to aid in method pruning. We unwrap it here.
+ if (context_->HasGeneratedMethods(descriptor_)) {
printer->Print(
- " try {\n"
- " return new $classname$(input, extensionRegistry);\n"
- " } catch (RuntimeException e) {\n"
- " if (e.getCause() instanceof\n"
- " com.google.protobuf.InvalidProtocolBufferException) {\n"
- " throw (com.google.protobuf.InvalidProtocolBufferException)\n"
- " e.getCause();\n"
- " }\n"
- " throw e;\n"
- " }\n",
+ " return new $classname$(input, extensionRegistry);\n",
"classname", descriptor_->name());
} else {
// When parsing constructor isn't generated, use builder to parse
@@ -1328,14 +1378,39 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
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 \"type.googleapis.com/\" + descriptor.getFullName();\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(message.getDescriptorForType()))\n"
+ " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
+ " message.getDescriptorForType()))\n"
+ " .setValue(message.toByteString())\n"
+ " .build();\n"
+ "}\n"
+ "\n"
+ "/**\n"
+ " * Packs a message uisng 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"
@@ -1344,8 +1419,8 @@ void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
" java.lang.Class<T> clazz) {\n"
" T defaultInstance =\n"
" com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
- " return getTypeUrl().equals(\n"
- " getTypeUrl(defaultInstance.getDescriptorForType()));\n"
+ " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+ " defaultInstance.getDescriptorForType().getFullName());\n"
"}\n"
"\n"
"private volatile com.google.protobuf.Message cachedUnpackValue;\n"
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index be5bfb07..e9fc57c2 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -56,6 +56,8 @@ namespace protobuf {
namespace compiler {
namespace java {
+static const int kMaxStaticSize = 1 << 15; // aka 32k
+
class MessageGenerator {
public:
explicit MessageGenerator(const Descriptor* descriptor);
@@ -64,7 +66,8 @@ class 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) = 0;
+ 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.
@@ -96,14 +99,15 @@ class ImmutableMessageGenerator : public MessageGenerator {
virtual void Generate(io::Printer* printer);
virtual void GenerateInterface(io::Printer* printer);
virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
- virtual void GenerateStaticVariables(io::Printer* printer);
+ virtual void GenerateStaticVariables(
+ io::Printer* printer, int* bytecode_estimate);
// Returns an estimate of the number of bytes the printed code will compile to
virtual int GenerateStaticVariableInitializers(io::Printer* printer);
private:
- void GenerateFieldAccessorTable(io::Printer* printer);
+ 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);
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index 5d535034..b3e9e986 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -81,8 +81,9 @@ MessageBuilderGenerator::MessageBuilderGenerator(
: descriptor_(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
- GOOGLE_CHECK_NE(
- FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+ GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A non-lite message generator is used to "
+ "generate lite messages.";
}
MessageBuilderGenerator::~MessageBuilderGenerator() {}
@@ -113,7 +114,7 @@ Generate(io::Printer* printer) {
GenerateDescriptorMethods(printer);
GenerateCommonBuilderMethods(printer);
- if (HasGeneratedMethods(descriptor_)) {
+ if (context_->HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer);
GenerateBuilderParsingMethods(printer);
}
@@ -134,7 +135,7 @@ Generate(io::Printer* printer) {
printer->Print(vars,
"public $oneof_capitalized_name$Case\n"
" get$oneof_capitalized_name$Case() {\n"
- " return $oneof_capitalized_name$Case.valueOf(\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
" $oneof_name$Case_);\n"
"}\n"
"\n"
@@ -439,7 +440,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
// -----------------------------------------------------------------
- if (HasGeneratedMethods(descriptor_)) {
+ if (context_->HasGeneratedMethods(descriptor_)) {
printer->Print(
"public Builder mergeFrom(com.google.protobuf.Message other) {\n"
" if (other instanceof $classname$) {\n"
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
index 8719d00d..dd429dc9 100644
--- a/src/google/protobuf/compiler/java/java_message_builder_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -81,8 +81,9 @@ MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
: descriptor_(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
- GOOGLE_CHECK_EQ(
- FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+ GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A lite message generator is used to "
+ "generate non-lite messages.";
}
MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
@@ -148,20 +149,6 @@ Generate(io::Printer* printer) {
.GenerateBuilderMembers(printer);
}
- if (!PreserveUnknownFields(descriptor_)) {
- printer->Print(
- "public final Builder setUnknownFields(\n"
- " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
- " return this;\n"
- "}\n"
- "\n"
- "public final Builder mergeUnknownFields(\n"
- " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
- " return this;\n"
- "}\n"
- "\n");
- }
-
printer->Print(
"\n"
"// @@protoc_insertion_point(builder_scope:$full_name$)\n",
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index b5f8e626..455516f6 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -70,8 +70,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+ (*variables)["on_changed"] = "onChanged();";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 356520ec..14281816 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -70,8 +70,6 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -288,11 +286,9 @@ void ImmutableMessageFieldLiteGenerator::
GenerateInitializationCode(io::Printer* printer) const {}
void ImmutableMessageFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " merge$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n");
}
void ImmutableMessageFieldLiteGenerator::
@@ -302,11 +298,18 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
void ImmutableMessageFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "$type$.Builder subBuilder = null;\n"
- "if ($is_field_present_message$) {\n"
- " subBuilder = $name$_.toBuilder();\n"
- "}\n");
+ // TODO(dweis): Update this code to avoid the builder allocation and instead
+ // only allocate a submessage that isn't made immutable. Rely on the top
+ // message calling makeImmutable once done to actually traverse the tree and
+ // finalize state. This will avoid:
+ // - transitive builder allocations
+ // - the extra transitive iteration for streamed fields
+ // - reallocations for copying repeated fields
+ 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_,
@@ -506,9 +509,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void ImmutableMessageOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "merge$capitalized_name$(other.get$capitalized_name$());\n");
+ "$oneof_name$_ = visitor.visitOneofMessage(\n"
+ " $has_oneof_case_message$,\n"
+ " $oneof_name$_,\n"
+ " other.$oneof_name$_);\n");
}
void ImmutableMessageOneofFieldLiteGenerator::
@@ -635,7 +641,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = newProtobufList($name$_);\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
" }\n"
"}\n"
"\n");
@@ -853,22 +860,9 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void RepeatedImmutableMessageFieldLiteGenerator::
-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.
- printer->Print(variables_,
- "if (!other.$name$_.isEmpty()) {\n"
- " if ($name$_.isEmpty()) {\n"
- " $name$_ = other.$name$_;\n"
- " } else {\n"
- " ensure$capitalized_name$IsMutable();\n"
- " $name$_.addAll(other.$name$_);\n"
- " }\n"
- " $on_changed$\n"
- "}\n");
+GenerateVisitCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_= visitor.visitList($name$_, other.$name$_);\n");
}
void RepeatedImmutableMessageFieldLiteGenerator::
@@ -881,7 +875,8 @@ void RepeatedImmutableMessageFieldLiteGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = newProtobufList();\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
"}\n");
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
index ae26c06a..61321547 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -67,7 +67,7 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -101,7 +101,7 @@ class ImmutableMessageOneofFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -125,7 +125,7 @@ class RepeatedImmutableMessageFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 94ed2c39..d4d2593a 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -46,7 +46,7 @@
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_enum_lite.h>
-#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_message_builder.h>
@@ -87,19 +87,20 @@ ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator(
: MessageGenerator(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
- GOOGLE_CHECK_EQ(
- FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+ GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+ << "Generator factory error: A lite message generator is used to "
+ "generate non-lite messages.";
}
ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
void ImmutableMessageLiteGenerator::GenerateStaticVariables(
- io::Printer* printer) {
+ 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);
+ .GenerateStaticVariables(printer, bytecode_estimate);
}
}
@@ -197,7 +198,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
}
printer->Indent();
- GenerateParsingConstructor(printer);
+
+ GenerateConstructor(printer);
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -259,12 +261,20 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
"cap_oneof_name",
ToUpper(vars["oneof_name"]));
printer->Print(vars,
- "private int value = 0;\n"
+ "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 < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -277,8 +287,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
}
printer->Print(
" case 0: return $cap_oneof_name$_NOT_SET;\n"
- " default: throw new java.lang.IllegalArgumentException(\n"
- " \"Value is undefined for this oneof enum.\");\n"
+ " default: return null;\n"
" }\n"
"}\n"
"public int getNumber() {\n"
@@ -291,7 +300,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print(vars,
"public $oneof_capitalized_name$Case\n"
"get$oneof_capitalized_name$Case() {\n"
- " return $oneof_capitalized_name$Case.valueOf(\n"
+ " return $oneof_capitalized_name$Case.forNumber(\n"
" $oneof_name$Case_);\n"
"}\n"
"\n"
@@ -313,11 +322,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
GenerateMessageSerializationMethods(printer);
- if (HasEqualsAndHashCode(descriptor_)) {
- GenerateEqualsAndHashCode(printer);
- }
-
-
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
@@ -334,16 +338,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
" Object arg0, Object arg1) {\n"
" switch (method) {\n"
- " case PARSE_PARTIAL_FROM: {\n"
- " return new $classname$("
- " (com.google.protobuf.CodedInputStream) arg0,\n"
- " (com.google.protobuf.ExtensionRegistryLite) arg1);\n"
- " }\n"
- " case NEW_INSTANCE: {\n"
- " return new $classname$(\n"
- " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
+ " case NEW_MUTABLE_INSTANCE: {\n"
+ " return new $classname$();\n"
" }\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -374,10 +370,18 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print(
"}\n"
- "case MERGE_FROM: {\n");
+ "case VISIT: {\n");
printer->Indent();
- GenerateDynamicMethodMergeFrom(printer);
+ GenerateDynamicMethodVisit(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case MERGE_FROM_STREAM: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodMergeFromStream(printer);
printer->Outdent();
printer->Print(
@@ -425,11 +429,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print(
"static {\n"
- " DEFAULT_INSTANCE = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
+ " DEFAULT_INSTANCE = new $classname$();\n"
+ " DEFAULT_INSTANCE.makeImmutable();\n"
"}\n"
"\n",
"classname", descriptor_->name());
@@ -446,7 +447,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
// 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_)
+ ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
.Generate(printer);
}
@@ -557,9 +558,6 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
" return size;\n"
"}\n"
"\n");
-
- printer->Print(
- "private static final long serialVersionUID = 0L;\n");
}
void ImmutableMessageLiteGenerator::
@@ -571,54 +569,62 @@ GenerateParseFromMethods(io::Printer* printer) {
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return parser().parseFrom(data);\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 parser().parseFrom(data, extensionRegistry);\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 parser().parseFrom(data);\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 parser().parseFrom(data, extensionRegistry);\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 parser().parseFrom(input);\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 parser().parseFrom(input, extensionRegistry);\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 parser().parseDelimitedFrom(input);\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 parser().parseDelimitedFrom(input, extensionRegistry);\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 parser().parseFrom(input);\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 parser().parseFrom(input, extensionRegistry);\n"
+ " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+ " DEFAULT_INSTANCE, input, extensionRegistry);\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -789,11 +795,13 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
io::Printer* printer) {
+
// Output generation code for each field.
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
.GenerateDynamicMethodMakeImmutableCode(printer);
}
+
printer->Print(
"return null;\n");
}
@@ -808,19 +816,17 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
// ===================================================================
-void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit(
io::Printer* printer) {
printer->Print(
- // Optimization: If other is the default instance, we know none of its
- // fields are set so we can skip the merge.
- "if (arg0 == $classname$.getDefaultInstance()) return this;\n"
- "$classname$ other = ($classname$) arg0;\n",
+ "Visitor visitor = (Visitor) arg0;\n"
+ "$classname$ other = ($classname$) arg1;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
field_generators_.get(
- descriptor_->field(i)).GenerateMergingCode(printer);
+ descriptor_->field(i)).GenerateVisitCode(printer);
}
}
@@ -839,7 +845,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
"field_name",
ToUpper(field->name()));
printer->Indent();
- field_generators_.get(field).GenerateMergingCode(printer);
+ field_generators_.get(field).GenerateVisitCode(printer);
printer->Print(
"break;\n");
printer->Outdent();
@@ -848,188 +854,66 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
}
printer->Print(
"case $cap_oneof_name$_NOT_SET: {\n"
+ " visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n"
" break;\n"
"}\n",
"cap_oneof_name",
ToUpper(context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name));
+ descriptor_->oneof_decl(i))->name),
+ "oneof_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
printer->Outdent();
printer->Print(
"}\n");
}
- // if message type has extensions
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "this.mergeExtensionFields(other);\n");
- }
-
- if (PreserveUnknownFields(descriptor_)) {
- printer->Print(
- "this.mergeUnknownFields(other.unknownFields);\n");
- }
-
printer->Print(
- "return this;\n");
-}
-
-// ===================================================================
-
-namespace {
-bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
- if (field->is_repeated()) {
- return false;
- }
- if (SupportFieldPresence(field->file())) {
- return true;
- }
- return GetJavaType(field) == JAVATYPE_MESSAGE &&
- field->containing_oneof() == NULL;
-}
-} // namespace
-
-void ImmutableMessageLiteGenerator::
-GenerateEqualsAndHashCode(io::Printer* printer) {
- printer->Print(
- "@java.lang.Override\n"
- "public boolean equals(final java.lang.Object obj) {\n");
+ "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n"
+ " .INSTANCE) {\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_));
-
- printer->Print("boolean result = true;\n");
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
- if (check_has_bits) {
- printer->Print(
- "result = result && (has$name$() == other.has$name$());\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");
- }
- }
- if (PreserveUnknownFields(descriptor_)) {
- // 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.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ const OneofDescriptor* field = descriptor_->oneof_decl(i);
printer->Print(
- "result = result && unknownFields.equals(other.unknownFields);\n");
+ "if (other.$oneof_name$Case_ != 0) {\n"
+ " $oneof_name$Case_ = other.$oneof_name$Case_;\n"
+ "}\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(field)->name);
}
- printer->Print(
- "return result;\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");
- // Include the hash of the class so that two objects with different types
- // but the same field values will probably have different hashes.
- printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ if (GenerateHasBits(descriptor_)) {
+ // 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 < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
- if (check_has_bits) {
+ for (int i = 0; i < totalInts; i++) {
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");
+ "$bit_field_name$ |= other.$bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
}
}
-
- printer->Print(
- "hash = (29 * hash) + unknownFields.hashCode();\n");
- printer->Print(
- "memoizedHashCode = hash;\n"
- "return hash;\n");
printer->Outdent();
printer->Print(
- "}\n"
- "\n");
-}
+ "}\n");
-// ===================================================================
-void ImmutableMessageLiteGenerator::
-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++) {
- ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
- .GenerateExtensionRegistrationCode(printer);
- }
+ printer->Print(
+ "return this;\n");
}
// ===================================================================
-void ImmutableMessageLiteGenerator::
-GenerateParsingConstructor(io::Printer* printer) {
- google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
- SortFieldsByNumber(descriptor_));
-
- printer->Print(
- "private $classname$(\n"
- " com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
- "classname", descriptor_->name());
- printer->Indent();
-
- // Initialize all fields to default.
- GenerateInitializers(printer);
-
- // Use builder bits to track mutable repeated fields.
- int totalBuilderBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const ImmutableFieldLiteGenerator& 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));
- }
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
+ io::Printer* printer) {
printer->Print(
+ "com.google.protobuf.CodedInputStream input =\n"
+ " (com.google.protobuf.CodedInputStream) arg0;\n"
+ "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n"
+ " (com.google.protobuf.ExtensionRegistryLite) arg1;\n"
"try {\n");
printer->Indent();
@@ -1077,6 +961,8 @@ GenerateParsingConstructor(io::Printer* printer) {
"}\n");
}
+ google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+ SortFieldsByNumber(descriptor_));
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
@@ -1130,19 +1016,54 @@ GenerateParsingConstructor(io::Printer* printer) {
"} 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);
+ printer->Outdent();
+ printer->Print(
+ "}\n"); // finally
+}
+
+// ===================================================================
+
+namespace {
+bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return false;
+ }
+ if (SupportFieldPresence(field->file())) {
+ return true;
+ }
+ return GetJavaType(field) == JAVATYPE_MESSAGE &&
+ field->containing_oneof() == NULL;
+}
+} // namespace
+
+// ===================================================================
+
+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(
- "doneParsing();\n");
+ "private $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Initialize all fields to default.
+ GenerateInitializers(printer);
- printer->Outdent();
printer->Outdent();
printer->Print(
- " }\n" // finally
"}\n");
}
@@ -1167,7 +1088,6 @@ void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
}
}
-
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
index 2bd3cdd4..292c1c56 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -54,7 +54,8 @@ class ImmutableMessageLiteGenerator : public MessageGenerator {
virtual void Generate(io::Printer* printer);
virtual void GenerateInterface(io::Printer* printer);
virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
- virtual void GenerateStaticVariables(io::Printer* printer);
+ virtual void GenerateStaticVariables(
+ io::Printer* printer, int* bytecode_estimate);
virtual int GenerateStaticVariableInitializers(io::Printer* printer);
private:
@@ -69,12 +70,13 @@ class ImmutableMessageLiteGenerator : public MessageGenerator {
void GenerateBuilder(io::Printer* printer);
void GenerateDynamicMethodIsInitialized(io::Printer* printer);
void GenerateDynamicMethodMakeImmutable(io::Printer* printer);
- void GenerateDynamicMethodMergeFrom(io::Printer* printer);
+ void GenerateDynamicMethodVisit(io::Printer* printer);
+ void GenerateDynamicMethodMergeFromStream(io::Printer* printer);
void GenerateDynamicMethodNewBuilder(io::Printer* printer);
void GenerateInitializers(io::Printer* printer);
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(io::Printer* printer);
- void GenerateParsingConstructor(io::Printer* printer);
+ void GenerateConstructor(io::Printer* printer);
Context* context_;
ClassNameResolver* name_resolver_;
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index 0c363f9f..bffe4f16 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -259,6 +259,13 @@ string ClassNameResolver::GetJavaImmutableClassName(
descriptor->file(), true);
}
+string ClassNameResolver::GetJavaImmutableClassName(
+ const EnumDescriptor* descriptor) {
+ return GetJavaClassFullName(
+ ClassNameWithoutPackage(descriptor, true),
+ descriptor->file(), true);
+}
+
} // namespace java
} // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h
index ab60b0a0..570d8d8f 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.h
+++ b/src/google/protobuf/compiler/java/java_name_resolver.h
@@ -98,6 +98,7 @@ class ClassNameResolver {
// For example:
// com.package.OuterClass$OuterMessage$InnerMessage
string GetJavaImmutableClassName(const Descriptor* descriptor);
+ string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
private:
// Get the full name of a Java class by prepending the Java package name
// or outer class name.
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index fe527623..3e4910c8 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -44,9 +44,10 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 178bbe19..e42ec280 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -75,12 +75,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
"" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
(*variables)["capitalized_type"] =
GetCapitalizedType(descriptor, /* immutable = */ true);
- if (descriptor->is_packed()) {
- (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
- descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
- } else {
- (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
- }
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
@@ -99,8 +94,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+ (*variables)["on_changed"] = "onChanged();";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -606,7 +600,7 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
if (descriptor_->is_packed() &&
- HasGeneratedMethods(descriptor_->containing_type())) {
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize = -1;\n");
}
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 5a7bf82d..690dad12 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -86,9 +86,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
case JAVATYPE_BOOLEAN:
(*variables)["field_list_type"] =
"com.google.protobuf.Internal." + capitalized_type + "List";
- (*variables)["new_list"] = "new" + capitalized_type + "List";
- (*variables)["new_list_with_capacity"] =
- "new" + capitalized_type + "ListWithCapacity";
(*variables)["empty_list"] = "empty" + capitalized_type + "List()";
(*variables)["make_name_unmodifiable"] =
(*variables)["name"] + "_.makeImmutable()";
@@ -98,19 +95,21 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*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)["new_list"] = "newProtobufList";
- (*variables)["new_list_with_capacity"] = "newProtobufListWithCapacity";
(*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 (IsReferenceType(GetJavaType(descriptor))) {
@@ -129,8 +128,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -299,17 +296,16 @@ GenerateBuilderClearCode(io::Printer* printer) const {
}
void ImmutablePrimitiveFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ "$name$_ = visitor.visit$visit_type$(\n"
+ " has$capitalized_name$(), $name$_,\n"
+ " other.has$capitalized_name$(), other.$name$_);\n");
} else {
printer->Print(variables_,
- "if (other.get$capitalized_name$() != $default$) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n"
+ " other.$name$_ != $default$, other.$name$_);\n");
}
}
@@ -541,9 +537,10 @@ GenerateBuildingCode(io::Printer* printer) const {
}
void ImmutablePrimitiveOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "set$capitalized_name$(other.get$capitalized_name$());\n");
+ "$oneof_name$_ = visitor.visitOneof$visit_type$(\n"
+ " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
}
void ImmutablePrimitiveOneofFieldLiteGenerator::
@@ -635,7 +632,7 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
if (descriptor_->options().packed() &&
- HasGeneratedMethods(descriptor_->containing_type())) {
+ context_->HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize = -1;\n");
}
@@ -643,7 +640,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = $new_list$($name$_);\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
" }\n"
"}\n");
@@ -744,22 +742,9 @@ GenerateBuilderClearCode(io::Printer* printer) const {
}
void RepeatedImmutablePrimitiveFieldLiteGenerator::
-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"
- " } else {\n"
- " ensure$capitalized_name$IsMutable();\n"
- " $name$_.addAll(other.$name$_);\n"
- " }\n"
- " $on_changed$\n"
- "}\n");
+GenerateVisitCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n");
}
void RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -780,7 +765,8 @@ GenerateParsingCode(io::Printer* printer) const {
// TODO(dweis): Scan the input buffer to count and ensure capacity.
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = $new_list$();\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
"}\n"
"$repeated_add$(input.read$capitalized_type$());\n");
}
@@ -797,10 +783,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
// TODO(dweis): Scan the input buffer to count, then initialize
// appropriately.
printer->Print(variables_,
- " $name$_ = $new_list$();\n");
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n");
} else {
printer->Print(variables_,
- " $name$_ = $new_list_with_capacity$(length/$fixed_size$);\n");
+ " final int currentSize = $name$_.size();\n"
+ " $name$_ = $name$_.mutableCopyWithCapacity(\n"
+ " currentSize + (length/$fixed_size$));\n");
}
// TODO(dweis): Scan the input buffer to count and ensure capacity.
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
index ad603c2a..6cfbbb98 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -69,7 +69,7 @@ class ImmutablePrimitiveFieldLiteGenerator
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateBuilderClearCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -105,7 +105,7 @@ class ImmutablePrimitiveOneofFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -130,7 +130,7 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
void GenerateBuilderClearCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 70177367..74253c3f 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -52,8 +52,9 @@ namespace compiler {
namespace java {
SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file)
- : name_resolver_(new ClassNameResolver), file_(file) {
-}
+ : name_resolver_(new ClassNameResolver),
+ enforce_lite_(false),
+ file_(file) {}
SharedCodeGenerator::~SharedCodeGenerator() {
}
@@ -63,7 +64,7 @@ void SharedCodeGenerator::Generate(GeneratorContext* context,
string java_package = FileJavaPackage(file_);
string package_dir = JavaPackageToDir(java_package);
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_, enforce_lite_)) {
// Generate descriptors.
string classname = name_resolver_->GetDescriptorClassName(file_);
string filename = package_dir + classname + ".java";
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
index 38a32fc2..3b573c07 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -72,6 +72,10 @@ class SharedCodeGenerator {
void Generate(GeneratorContext* generator_context,
vector<string>* file_list);
+ void SetEnforceLite(bool value) {
+ enforce_lite_ = value;
+ }
+
void GenerateDescriptors(io::Printer* printer);
private:
@@ -81,6 +85,7 @@ class SharedCodeGenerator {
bool ShouldIncludeDependency(const FileDescriptor* descriptor);
google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
+ bool enforce_lite_;
const FileDescriptor* file_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
};
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 7f757e47..b67eeb53 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -87,8 +87,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+ (*variables)["on_changed"] = "onChanged();";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -408,15 +407,6 @@ GenerateParsingCode(io::Printer* printer) const {
"java.lang.String s = input.readStringRequireUtf8();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
- // Lite runtime should attempt to reduce allocations by attempting to
- // construct the string directly from the input stream buffer. This avoids
- // spurious intermediary ByteString allocations, cutting overall allocations
- // in half.
- printer->Print(variables_,
- "java.lang.String s = input.readString();\n"
- "$set_has_field_bit_message$\n"
- "$name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -668,15 +658,6 @@ GenerateParsingCode(io::Printer* printer) const {
"java.lang.String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
- // Lite runtime should attempt to reduce allocations by attempting to
- // construct the string directly from the input stream buffer. This avoids
- // spurious intermediary ByteString allocations, cutting overall allocations
- // in half.
- printer->Print(variables_,
- "java.lang.String s = input.readString();\n"
- "$set_oneof_case_message$;\n"
- "$oneof_name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -934,13 +915,6 @@ GenerateParsingCode(io::Printer* printer) const {
if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"java.lang.String s = input.readStringRequireUtf8();\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
- // Lite runtime should attempt to reduce allocations by attempting to
- // construct the string directly from the input stream buffer. This avoids
- // spurious intermediary ByteString allocations, cutting overall allocations
- // in half.
- printer->Print(variables_,
- "java.lang.String s = input.readString();\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n");
@@ -950,7 +924,7 @@ GenerateParsingCode(io::Printer* printer) const {
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
" $set_mutable_bit_parser$;\n"
"}\n");
- if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+ if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"$name$_.add(s);\n");
} else {
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index eb5964bd..0b92c021 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -84,8 +84,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// by the proto compiler
(*variables)["deprecation"] = descriptor->options().deprecated()
? "@java.lang.Deprecated " : "";
- (*variables)["on_changed"] =
- HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
if (SupportFieldPresence(descriptor->file())) {
// For singular messages and builders, one bit is used for the hasField bit.
@@ -103,7 +101,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["clear_has_field_bit_message"] = "";
(*variables)["is_field_present_message"] =
- "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
+ "!" + (*variables)["name"] + "_.isEmpty()";
}
// For repeated builders, the underlying list tracks mutability state.
@@ -301,22 +299,16 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void ImmutableStringFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
- // 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_message$\n"
- " $name$_ = other.$name$_;\n"
- " $on_changed$\n"
- "}\n");
+ "$name$_ = visitor.visitString(\n"
+ " has$capitalized_name$(), $name$_,\n"
+ " other.has$capitalized_name$(), other.$name$_);\n");
} else {
printer->Print(variables_,
- "if (!other.get$capitalized_name$().isEmpty()) {\n"
- " $name$_ = other.$name$_;\n"
- " $on_changed$\n"
- "}\n");
+ "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n"
+ " !other.$name$_.isEmpty(), other.$name$_);\n");
}
}
@@ -523,13 +515,10 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void ImmutableStringOneofFieldLiteGenerator::
-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.
+GenerateVisitCode(io::Printer* printer) const {
printer->Print(variables_,
- "$set_oneof_case_message$;\n"
- "$oneof_name$_ = other.$oneof_name$_;\n"
- "$on_changed$\n");
+ "$oneof_name$_ = visitor.visitOneofString(\n"
+ " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
}
void ImmutableStringOneofFieldLiteGenerator::
@@ -650,8 +639,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
- " $name$_);\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
" }\n"
"}\n");
@@ -778,22 +767,9 @@ GenerateInitializationCode(io::Printer* printer) const {
}
void RepeatedImmutableStringFieldLiteGenerator::
-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"
- " } else {\n"
- " ensure$capitalized_name$IsMutable();\n"
- " $name$_.addAll(other.$name$_);\n"
- " }\n"
- " $on_changed$\n"
- "}\n");
+GenerateVisitCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_= visitor.visitList($name$_, other.$name$_);\n");
}
void RepeatedImmutableStringFieldLiteGenerator::
@@ -817,15 +793,11 @@ GenerateParsingCode(io::Printer* printer) const {
}
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
+ " $name$_ =\n"
+ " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
"}\n");
- if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
- printer->Print(variables_,
- "$name$_.add(s);\n");
- } else {
- printer->Print(variables_,
- "$name$_.add(bs);\n");
- }
+ printer->Print(variables_,
+ "$name$_.add(s);\n");
}
void RepeatedImmutableStringFieldLiteGenerator::
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
index 4d9b4bd7..4148aa4d 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -68,7 +68,7 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -103,7 +103,7 @@ class ImmutableStringOneofFieldLiteGenerator
private:
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -126,7 +126,7 @@ class RepeatedImmutableStringFieldLiteGenerator
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
void GenerateInitializationCode(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateVisitCode(io::Printer* printer) const;
void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingDoneCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index a33eba1b..7c3a0421 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -68,12 +68,10 @@ void UpdateParamsRecursively(Params& params,
}
if (file->options().has_java_package()) {
string result = file->options().java_package();
- if (!file->options().javanano_use_deprecated_package()) {
- if (!result.empty()) {
- result += ".";
- }
- result += "nano";
+ if (!result.empty()) {
+ result += ".";
}
+ result += "nano";
params.set_java_package(
file->name(), result);
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 5465655f..02811a24 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -201,12 +201,10 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) {
result += file->package();
}
- if (!file->options().javanano_use_deprecated_package()) {
- if (!result.empty()) {
- result += ".";
- }
- result += "nano";
+ if (!result.empty()) {
+ result += ".";
}
+ result += "nano";
return result;
}
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 0de7e2c6..3de61e80 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -28,7 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <google/protobuf/compiler/js/js_generator.h>
+#include "google/protobuf/compiler/js/js_generator.h"
#include <assert.h>
#include <algorithm>
@@ -123,6 +123,16 @@ 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 string& ident) {
for (int i = 0; i < kNumKeyword; i++) {
if (ident == kKeyword[i]) {
@@ -134,7 +144,7 @@ bool IsReserved(const string& ident) {
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
-// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
+// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
string StripProto(const string& filename) {
const char* suffix = HasSuffixString(filename, ".protodevel")
? ".protodevel" : ".proto";
@@ -144,9 +154,7 @@ string StripProto(const string& filename) {
// Given a filename like foo/bar/baz.proto, returns the correspoding JavaScript
// file foo/bar/baz.js.
string GetJSFilename(const string& filename) {
- const char* suffix = HasSuffixString(filename, ".protodevel")
- ? ".protodevel" : ".proto";
- return StripSuffixString(filename, suffix) + "_pb.js";
+ return StripProto(filename) + "_pb.js";
}
// Given a filename like foo/bar/baz.proto, returns the root directory
@@ -385,15 +393,47 @@ string ToFileName(const string& input) {
return result;
}
+// When we're generating one output file per type name, this is the filename
+// that top-level extensions should go in.
+string GetExtensionFileName(const GeneratorOptions& options,
+ const FileDescriptor* file) {
+ return options.output_dir + "/" + ToFileName(GetPath(options, file)) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetMessageFileName(const GeneratorOptions& options,
+ const Descriptor* desc) {
+ return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetEnumFileName(const GeneratorOptions& options,
+ const EnumDescriptor* desc) {
+ return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+}
+
// Returns the message/response ID, if set.
string GetMessageId(const Descriptor* desc) {
return string();
}
+bool IgnoreExtensionField(const FieldDescriptor* field) {
+ // Exclude descriptor extensions from output "to avoid clutter" (from original
+ // codegen).
+ return field->is_extension() &&
+ field->containing_type()->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 false; }
+
+bool IgnoreField(const FieldDescriptor* field) {
+ return IgnoreExtensionField(field);
+}
// Does JSPB ignore this entire oneof? True only if all fields are ignored.
@@ -438,12 +478,32 @@ string JSObjectFieldName(const FieldDescriptor* field) {
return name;
}
+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);
+ }
+}
+
// Returns the field name as a capitalized portion of a getter/setter method
// name, e.g. MyField for .getMyField().
-string JSGetterName(const FieldDescriptor* field) {
+string JSGetterName(const FieldDescriptor* field,
+ BytesMode bytes_mode = BYTES_DEFAULT) {
string name = JSIdent(field,
/* is_upper_camel = */ true,
/* is_map = */ false);
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ string suffix = JSByteGetterSuffix(bytes_mode);
+ if (!suffix.empty()) {
+ name += "_as" + suffix;
+ }
+ }
if (name == "Extension" || name == "JsPbMessageId") {
// Avoid conflicts with base-class names.
name += "$";
@@ -504,8 +564,7 @@ string JSOneofIndex(const OneofDescriptor* oneof) {
return SimpleItoa(index);
}
-// Decodes a codepoint in \x0000 -- \xFFFF. Since JS strings are UTF-16, we only
-// need to handle the BMP (16-bit range) here.
+// Decodes a codepoint in \x0000 -- \xFFFF.
uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
if (*length == 0) {
return 0;
@@ -542,80 +601,56 @@ uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
}
// Escapes the contents of a string to be included within double-quotes ("") in
-// JavaScript. |is_utf8| determines whether the input data (in a C++ string of
-// chars) is UTF-8 encoded (in which case codepoints become JavaScript string
-// characters, escaped with 16-bit hex escapes where necessary) or raw binary
-// (in which case bytes become JavaScript string characters 0 -- 255).
-string EscapeJSString(const string& in, bool is_utf8) {
- string result;
+// 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(lukestebbing): Support codepoints outside the BMP.
+bool EscapeJSString(const string& in, string* out) {
size_t decoded = 0;
for (size_t i = 0; i < in.size(); i += decoded) {
uint16 codepoint = 0;
- if (is_utf8) {
- // Decode the next UTF-8 codepoint.
- size_t have_bytes = in.size() - i;
- uint8 bytes[3] = {
+ // 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) {
- break;
- }
- decoded = have_bytes;
- } else {
- codepoint = static_cast<uint16>(static_cast<uint8>(in[i]));
- decoded = 1;
+ };
+ codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
+ if (have_bytes == 0) {
+ return false;
}
-
- // Next byte -- used for minimal octal escapes below.
- char next_byte = (i + decoded) < in.size() ?
- in[i + decoded] : 0;
- bool pad_octal = (next_byte >= '0' && next_byte <= '7');
+ decoded = have_bytes;
switch (codepoint) {
- case '\0': result += pad_octal ? "\\000" : "\\0"; break;
- case '\b': result += "\\\b"; break;
- case '\t': result += "\\\t"; break;
- case '\n': result += "\\\n"; break;
- case '\r': result += "\\\r"; break;
- case '\f': result += "\\\f"; break;
- case '\\': result += "\\\\"; break;
- case '"': result += pad_octal ? "\\042" : "\\42"; break;
- case '&': result += pad_octal ? "\\046" : "\\46"; break;
- case '\'': result += pad_octal ? "\\047" : "\\47"; break;
- case '<': result += pad_octal ? "\\074" : "\\74"; break;
- case '=': result += pad_octal ? "\\075" : "\\75"; break;
- case '>': result += pad_octal ? "\\076" : "\\76"; break;
+ 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:
- // All other non-ASCII codepoints are escaped.
- // Original codegen uses hex for >= 0x100 and octal for others.
+ // TODO(lukestebbing): 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) {
- result += static_cast<char>(codepoint);
+ *out += static_cast<char>(codepoint);
+ } else if (codepoint >= 0x100) {
+ *out += StringPrintf("\\u%04x", codepoint);
} else {
- if (codepoint >= 0x100) {
- result += StringPrintf("\\u%04x", codepoint);
- } else {
- if (pad_octal || codepoint >= 0100) {
- result += "\\";
- result += ('0' + ((codepoint >> 6) & 07));
- result += ('0' + ((codepoint >> 3) & 07));
- result += ('0' + ((codepoint >> 0) & 07));
- } else if (codepoint >= 010) {
- result += "\\";
- result += ('0' + ((codepoint >> 3) & 07));
- result += ('0' + ((codepoint >> 0) & 07));
- } else {
- result += "\\";
- result += ('0' + ((codepoint >> 0) & 07));
- }
- }
+ *out += StringPrintf("\\x%02x", codepoint);
}
break;
}
}
- return result;
+ return true;
}
string EscapeBase64(const string& in) {
@@ -740,11 +775,17 @@ string JSFieldDefault(const FieldDescriptor* field) {
return DoubleToString(field->default_value_double());
case FieldDescriptor::CPPTYPE_STRING:
if (field->type() == FieldDescriptor::TYPE_STRING) {
- return "\"" + EscapeJSString(field->default_value_string(), true) +
- "\"";
- } else {
- return "\"" + EscapeBase64(field->default_value_string()) +
- "\"";
+ string out;
+ bool is_valid = EscapeJSString(field->default_value_string(), &out);
+ if (!is_valid) {
+ // TODO(lukestebbing): 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";
@@ -801,8 +842,27 @@ string JSIntegerTypeName(const FieldDescriptor* field) {
return "number";
}
+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";
+}
+
string JSTypeName(const GeneratorOptions& options,
- const FieldDescriptor* field) {
+ const FieldDescriptor* field,
+ BytesMode bytes_mode) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_BOOL:
return "boolean";
@@ -819,7 +879,7 @@ string JSTypeName(const GeneratorOptions& options,
case FieldDescriptor::CPPTYPE_DOUBLE:
return "number";
case FieldDescriptor::CPPTYPE_STRING:
- return "string";
+ return JSStringTypeName(options, field, bytes_mode);
case FieldDescriptor::CPPTYPE_ENUM:
return GetPath(options, field->enum_type());
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -836,20 +896,26 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options,
bool force_optional,
bool force_present,
bool singular_if_not_packed,
- bool always_singular) {
+ BytesMode bytes_mode = BYTES_DEFAULT) {
bool is_primitive =
(field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
- field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE);
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
+ (field->type() != FieldDescriptor::TYPE_BYTES ||
+ bytes_mode == BYTES_B64));
- string jstype = JSTypeName(options, field);
+ string jstype = JSTypeName(options, field, bytes_mode);
if (field->is_repeated() &&
- !always_singular &&
(field->is_packed() || !singular_if_not_packed)) {
- if (!is_primitive) {
- jstype = "!" + jstype;
+ if (field->type() == FieldDescriptor::TYPE_BYTES &&
+ bytes_mode == BYTES_DEFAULT) {
+ jstype = "(Array<!Uint8Array>|Array<string>)";
+ } else {
+ if (!is_primitive) {
+ jstype = "!" + jstype;
+ }
+ jstype = "Array.<" + jstype + ">";
}
- jstype = "Array.<" + jstype + ">";
if (!force_optional) {
jstype = "!" + jstype;
}
@@ -884,10 +950,6 @@ string JSBinaryReaderMethodType(const FieldDescriptor* field) {
string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
bool is_writer) {
string name = JSBinaryReaderMethodType(field);
- if (is_writer && field->type() == FieldDescriptor::TYPE_BYTES) {
- // Override for `bytes` fields: treat string as raw bytes, not base64.
- name = "BytesRawString";
- }
if (field->is_packed()) {
name = "Packed" + name;
} else if (is_writer && field->is_repeated()) {
@@ -1044,7 +1106,7 @@ string FieldDefinition(const GeneratorOptions& options,
field->number());
}
-string FieldComments(const FieldDescriptor* field) {
+string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
string comments;
if (field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL) {
comments +=
@@ -1060,6 +1122,11 @@ string FieldComments(const FieldDescriptor* field) {
" * replace the array itself, then you must call the setter to "
"update it.\n";
}
+ 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;
}
@@ -1070,8 +1137,10 @@ bool ShouldGenerateExtension(const FieldDescriptor* field) {
}
bool HasExtensions(const Descriptor* desc) {
- if (desc->extension_count() > 0) {
- return true;
+ 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))) {
@@ -1123,7 +1192,7 @@ string GetPivot(const Descriptor* desc) {
}
// Returns true for fields that represent "null" as distinct from the default
-// value. See https://go/proto3#heading=h.kozewqqcqhuz for more information.
+// value. See http://go/proto3#heading=h.kozewqqcqhuz for more information.
bool HasFieldPresence(const FieldDescriptor* field) {
return
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
@@ -1132,7 +1201,7 @@ bool HasFieldPresence(const FieldDescriptor* field) {
}
// For proto3 fields without presence, returns a string representing the default
-// value in JavaScript. See https://go/proto3#heading=h.kozewqqcqhuz for more
+// value in JavaScript. See http://go/proto3#heading=h.kozewqqcqhuz for more
// information.
string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
switch (field->cpp_type()) {
@@ -1151,16 +1220,153 @@ string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_BOOL:
return "false";
- case FieldDescriptor::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_STRING: // includes BYTES
return "\"\"";
default:
- // BYTES and MESSAGE are handled separately.
+ // MESSAGE is handled separately.
assert(false);
return "";
}
}
+// We use this to implement the semantics that same file can be generated
+// multiple times, but the last one wins. 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)
+ : error_on_conflict_(options.error_on_name_conflict) {}
+
+ bool AddFile(const string& filename, const void* desc, string* error) {
+ if (descs_by_filename_.find(filename) != descs_by_filename_.end()) {
+ if (error_on_conflict_) {
+ *error = "Name conflict: file name " + filename +
+ " would be generated by two descriptors";
+ return false;
+ }
+ allowed_descs_.erase(descs_by_filename_[filename]);
+ }
+
+ descs_by_filename_[filename] = desc;
+ allowed_descs_.insert(desc);
+ return true;
+ }
+
+ void GetAllowedSet(set<const void*>* allowed_set) {
+ *allowed_set = allowed_descs_;
+ }
+
+ private:
+ bool error_on_conflict_;
+ map<string, const void*> descs_by_filename_;
+ set<const void*> allowed_descs_;
+};
+
+void DepthFirstSearch(const FileDescriptor* file,
+ vector<const FileDescriptor*>* list,
+ 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 set<const FileDescriptor*>& file_set)
+ : file_set_(file_set) {}
+
+ bool operator()(const FileDescriptor* file) {
+ return file_set_.count(file) == 0;
+ }
+
+ private:
+ const 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 vector<const FileDescriptor*>& input,
+ 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();
+ set<const FileDescriptor*> seen;
+ 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.
+
+bool GenerateJspbAllowedSet(const GeneratorOptions& options,
+ const vector<const FileDescriptor*>& files,
+ set<const void*>* allowed_set,
+ string* error) {
+ vector<const FileDescriptor*> files_ordered;
+ GenerateJspbFileOrder(files, &files_ordered);
+
+ // Choose the last descriptor for each filename.
+ FileDeduplicator dedup(options);
+ 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 (!dedup.AddFile(GetMessageFileName(options, desc), desc, error)) {
+ 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(GetEnumFileName(options, desc), desc, error)) {
+ 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(GetExtensionFileName(options, files_ordered[i]),
+ files_ordered[i], error)) {
+ return false;
+ }
+ }
+ }
+
+ dedup.GetAllowedSet(allowed_set);
+
+ return true;
+}
+
} // anonymous namespace
void Generator::GenerateHeader(const GeneratorOptions& options,
@@ -1251,10 +1457,10 @@ void Generator::GenerateProvides(const GeneratorOptions& options,
}
}
-void Generator::GenerateRequires(const GeneratorOptions& options,
- io::Printer* printer,
- const Descriptor* desc,
- std::set<string>* provided) const {
+void Generator::GenerateRequiresForMessage(const GeneratorOptions& options,
+ io::Printer* printer,
+ const Descriptor* desc,
+ std::set<string>* provided) const {
std::set<string> required;
std::set<string> forwards;
bool have_message = false;
@@ -1266,55 +1472,50 @@ void Generator::GenerateRequires(const GeneratorOptions& options,
/* require_extension = */ HasExtensions(desc));
}
-void Generator::GenerateRequires(const GeneratorOptions& options,
- io::Printer* printer,
- const vector<const FileDescriptor*>& files,
- std::set<string>* provided) const {
- if (options.import_style == GeneratorOptions::IMPORT_BROWSER) {
- return;
- } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
- // For Closure imports we need to import every message type individually.
- std::set<string> required;
- std::set<string> forwards;
- bool have_extensions = false;
- bool have_message = false;
+void Generator::GenerateRequiresForLibrary(
+ const GeneratorOptions& options, io::Printer* printer,
+ const vector<const FileDescriptor*>& files,
+ std::set<string>* provided) const {
+ GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::IMPORT_CLOSURE);
+ // For Closure imports we need to import every message type individually.
+ std::set<string> required;
+ std::set<string> forwards;
+ bool have_extensions = false;
+ bool have_message = false;
- for (int i = 0; i < files.size(); i++) {
- for (int j = 0; j < files[i]->message_type_count(); j++) {
- FindRequiresForMessage(options,
- files[i]->message_type(j),
- &required, &forwards, &have_message);
- }
- if (!have_extensions && HasExtensions(files[i])) {
- have_extensions = true;
- }
+ for (int i = 0; i < files.size(); i++) {
+ for (int j = 0; j < files[i]->message_type_count(); j++) {
+ FindRequiresForMessage(options,
+ files[i]->message_type(j),
+ &required, &forwards, &have_message);
+ }
+ if (!have_extensions && HasExtensions(files[i])) {
+ have_extensions = 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(GetPath(options, extension->containing_type()));
- }
- FindRequiresForField(options, extension, &required, &forwards);
- have_extensions = 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(GetPath(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);
- } else if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
- // CommonJS imports are based on files
}
+
+ GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+ /* require_jspb = */ have_message,
+ /* require_extension = */ have_extensions);
}
-void Generator::GenerateRequires(const GeneratorOptions& options,
- io::Printer* printer,
- const vector<const FieldDescriptor*>& fields,
- std::set<string>* provided) const {
+void Generator::GenerateRequiresForExtensions(
+ const GeneratorOptions& options, io::Printer* printer,
+ const vector<const FieldDescriptor*>& fields,
+ std::set<string>* provided) const {
std::set<string> required;
std::set<string> forwards;
for (int i = 0; i < fields.size(); i++) {
@@ -1708,7 +1909,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
printer->Print(
" if (includeInstance) {\n"
- " obj.$$jspbMessageInstance = msg\n"
+ " obj.$$jspbMessageInstance = msg;\n"
" }\n"
" return obj;\n"
"};\n"
@@ -1741,17 +1942,34 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
}
} else {
// Simple field (singular or repeated).
- if (!HasFieldPresence(field) && !field->is_repeated()) {
+ if ((!HasFieldPresence(field) && !field->is_repeated()) ||
+ field->type() == FieldDescriptor::TYPE_BYTES) {
// Delegate to the generated get<field>() method in order not to duplicate
- // the proto3-field-default-value logic here.
+ // the proto3-field-default-value or byte-coercion logic here.
printer->Print("msg.get$getter$()",
- "getter", JSGetterName(field));
+ "getter", JSGetterName(field, BYTES_B64));
} else {
if (field->has_default_value()) {
- printer->Print("jspb.Message.getField(msg, $index$) != null ? "
- "jspb.Message.getField(msg, $index$) : $defaultValue$",
+ printer->Print("jspb.Message.getField(msg, $index$) == null ? "
+ "$defaultValue$ : ",
"index", JSFieldIndex(field),
"defaultValue", JSFieldDefault(field));
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+ if (field->is_repeated()) {
+ printer->Print("jspb.Message.getRepeatedFloatingPointField("
+ "msg, $index$)",
+ "index", JSFieldIndex(field));
+ } else if (field->is_optional() && !field->has_default_value()) {
+ printer->Print("jspb.Message.getOptionalFloatingPointField("
+ "msg, $index$)",
+ "index", JSFieldIndex(field));
+ } else {
+ // Convert "NaN" to NaN.
+ printer->Print("+jspb.Message.getField(msg, $index$)",
+ "index", JSFieldIndex(field));
+ }
} else {
printer->Print("jspb.Message.getField(msg, $index$)",
"index", JSFieldIndex(field));
@@ -1860,6 +2078,40 @@ void Generator::GenerateClassFields(const GeneratorOptions& options,
}
}
+void GenerateBytesWrapper(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field,
+ BytesMode bytes_mode) {
+ string type =
+ JSFieldTypeAnnotation(options, field,
+ /* force_optional = */ false,
+ /* force_present = */ !HasFieldPresence(field),
+ /* 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", GetPath(options, field->containing_type()),
+ "name", JSGetterName(field, bytes_mode),
+ "list", field->is_repeated() ? "List" : "",
+ "suffix", JSByteGetterSuffix(bytes_mode),
+ "defname", JSGetterName(field, BYTES_DEFAULT));
+}
+
+
void Generator::GenerateClassField(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
@@ -1871,12 +2123,11 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
" * @return {$type$}\n"
" */\n",
"fielddef", FieldDefinition(options, field),
- "comment", FieldComments(field),
+ "comment", FieldComments(field, BYTES_DEFAULT),
"type", JSFieldTypeAnnotation(options, field,
/* force_optional = */ false,
/* force_present = */ false,
- /* singular_if_not_packed = */ false,
- /* always_singular = */ false));
+ /* singular_if_not_packed = */ false));
printer->Print(
"$class$.prototype.get$name$ = function() {\n"
" return /** @type{$type$} */ (\n"
@@ -1890,8 +2141,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"type", JSFieldTypeAnnotation(options, field,
/* force_optional = */ false,
/* force_present = */ false,
- /* singular_if_not_packed = */ false,
- /* always_singular = */ false),
+ /* singular_if_not_packed = */ false),
"rpt", (field->is_repeated() ? "Repeated" : ""),
"index", JSFieldIndex(field),
"wrapperclass", SubmessageTypeRef(options, field),
@@ -1905,8 +2155,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
JSFieldTypeAnnotation(options, field,
/* force_optional = */ true,
/* force_present = */ false,
- /* singular_if_not_packed = */ false,
- /* always_singular = */ false),
+ /* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field),
"class", GetPath(options, field->containing_type()),
"name", JSGetterName(field),
@@ -1935,15 +2184,29 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"returnvalue", JSReturnClause(field));
} else {
- string typed_annotation;
+ bool untyped =
+ false;
// Simple (primitive) field, either singular or repeated.
- {
- typed_annotation = JSFieldTypeAnnotation(options, field,
+
+ // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
+ // at this point we "lie" to non-binary users and tell the 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;
+ string typed_annotation =
+ JSFieldTypeAnnotation(options, field,
/* force_optional = */ false,
/* force_present = */ !HasFieldPresence(field),
/* singular_if_not_packed = */ false,
- /* always_singular = */ false),
+ /* bytes_mode = */ bytes_mode);
+ if (untyped) {
+ printer->Print(
+ "/**\n"
+ " * @return {?} Raw field, untyped.\n"
+ " */\n");
+ } else {
printer->Print(
"/**\n"
" * $fielddef$\n"
@@ -1951,7 +2214,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
" * @return {$type$}\n"
" */\n",
"fielddef", FieldDefinition(options, field),
- "comment", FieldComments(field),
+ "comment", FieldComments(field, bytes_mode),
"type", typed_annotation);
}
@@ -1960,7 +2223,10 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"class", GetPath(options, field->containing_type()),
"name", JSGetterName(field));
- {
+ if (untyped) {
+ printer->Print(
+ " return ");
+ } else {
printer->Print(
" return /** @type {$type$} */ (",
"type", typed_annotation);
@@ -1975,17 +2241,39 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"default", Proto3PrimitiveFieldDefault(field));
} else {
if (field->has_default_value()) {
- printer->Print("jspb.Message.getField(this, $index$) != null ? "
- "jspb.Message.getField(this, $index$) : $defaultValue$",
+ printer->Print("jspb.Message.getField(this, $index$) == null ? "
+ "$defaultValue$ : ",
"index", JSFieldIndex(field),
"defaultValue", JSFieldDefault(field));
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
+ if (field->is_repeated()) {
+ printer->Print("jspb.Message.getRepeatedFloatingPointField("
+ "this, $index$)",
+ "index", JSFieldIndex(field));
+ } else if (field->is_optional() && !field->has_default_value()) {
+ printer->Print("jspb.Message.getOptionalFloatingPointField("
+ "this, $index$)",
+ "index", JSFieldIndex(field));
+ } else {
+ // Convert "NaN" to NaN.
+ printer->Print("+jspb.Message.getField(this, $index$)",
+ "index", JSFieldIndex(field));
+ }
} else {
printer->Print("jspb.Message.getField(this, $index$)",
"index", JSFieldIndex(field));
}
}
- {
+ if (untyped) {
+ printer->Print(
+ ";\n"
+ "};\n"
+ "\n"
+ "\n");
+ } else {
printer->Print(
");\n"
"};\n"
@@ -1993,18 +2281,27 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"\n");
}
- {
+ if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
+ GenerateBytesWrapper(options, printer, field, BYTES_B64);
+ GenerateBytesWrapper(options, printer, field, BYTES_U8);
+ }
+
+ if (untyped) {
+ printer->Print(
+ "/**\n"
+ " * @param {*} value $returndoc$\n"
+ " */\n",
+ "returndoc", JSReturnDoc(options, field));
+ } else {
printer->Print(
"/** @param {$optionaltype$} value $returndoc$ */\n",
"optionaltype",
JSFieldTypeAnnotation(options, field,
/* force_optional = */ true,
/* force_present = */ !HasFieldPresence(field),
- /* singular_if_not_packed = */ false,
- /* always_singular = */ false),
+ /* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field));
}
-
printer->Print(
"$class$.prototype.set$name$ = function(value) {\n"
" jspb.Message.set$oneoftag$Field(this, $index$",
@@ -2017,14 +2314,22 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"};\n"
"\n"
"\n",
- "type", "",
- "typeclose", "",
+ "type",
+ untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+ "typeclose", untyped ? ")" : "",
"oneofgroup",
(field->containing_oneof() ? (", " + JSOneofArray(options, field))
: ""),
"returnvalue", JSReturnClause(field), "rptvalueinit",
(field->is_repeated() ? " || []" : ""));
+ if (untyped) {
+ printer->Print(
+ "/**\n"
+ " * Clears the value. $returndoc$\n"
+ " */\n",
+ "returndoc", JSReturnDoc(options, field));
+ }
if (HasFieldPresence(field)) {
printer->Print(
@@ -2162,16 +2467,18 @@ void Generator::GenerateClassDeserializeBinaryField(
" var value = /** @type {$fieldtype$} */ (reader.$reader$());\n",
"fieldtype", JSFieldTypeAnnotation(options, field, false, true,
/* singular_if_not_packed = */ true,
- /* always_singular = */ false),
+ BYTES_U8),
"reader", JSBinaryReaderMethodName(field));
}
if (field->is_repeated() && !field->is_packed()) {
// Repeated fields receive a |value| one at at a time; append to array
- // returned by get$name$().
- printer->Print(
- " msg.get$name$().push(value);\n",
- "name", JSGetterName(field));
+ // returned by get$name$(). Annoyingly, we have to call 'set' after
+ // changing the array.
+ printer->Print(" msg.get$name$().push(value);\n", "name",
+ JSGetterName(field));
+ printer->Print(" msg.set$name$(msg.get$name$());\n", "name",
+ JSGetterName(field));
} 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
@@ -2244,7 +2551,7 @@ void Generator::GenerateClassSerializeBinaryField(
const FieldDescriptor* field) const {
printer->Print(
" f = this.get$name$();\n",
- "name", JSGetterName(field));
+ "name", JSGetterName(field, BYTES_U8));
if (field->is_repeated()) {
printer->Print(
@@ -2294,7 +2601,6 @@ void Generator::GenerateClassSerializeBinaryField(
" $index$,\n"
" f",
"writer", JSBinaryWriterMethodName(field),
- "name", JSGetterName(field),
"index", SimpleItoa(field->number()));
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -2356,8 +2662,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
options, field,
/* force_optional = */ false,
/* force_present = */ true,
- /* singular_if_not_packed = */ false,
- /* always_singular = */ false));
+ /* singular_if_not_packed = */ false));
printer->Print(
" $index$,\n"
" {$name$: 0},\n"
@@ -2528,7 +2833,7 @@ void Generator::GenerateFile(const GeneratorOptions& options,
printer->Print("var global = Function('return this')();\n\n");
for (int i = 0; i < file->dependency_count(); i++) {
- const std::string& name = file->dependency(i)->name();
+ const string& name = file->dependency(i)->name();
printer->Print(
"var $alias$ = require('$file$');\n",
"alias", ModuleAlias(name),
@@ -2543,7 +2848,7 @@ void Generator::GenerateFile(const GeneratorOptions& options,
//
// // Later generated code expects foo.bar = {} to exist:
// foo.bar.Baz = function() { /* ... */ }
- std::set<std::string> provided;
+ set<string> provided;
// Cover the case where this file declares extensions but no messages.
// This will ensure that the file-level object will be declared to hold
@@ -2615,7 +2920,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
FindProvidesForFields(options, &printer, extensions, &provided);
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
- GenerateRequires(options, &printer, files, &provided);
+ GenerateRequiresForLibrary(options, &printer, files, &provided);
GenerateFilesInDepOrder(options, &printer, files);
@@ -2629,66 +2934,20 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
return false;
}
} else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
- // Collect all types, and print each type to a separate file. Pull out
- // free-floating extensions while we make this pass.
- map< string, vector<const FieldDescriptor*> > extensions_by_namespace;
-
- // 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.
-
- // Current descriptor that will generate each filename, indexed by filename.
- map<string, const void*> desc_by_filename;
- // Set of descriptors allowed to generate files.
- set<const void*> allowed_descs;
-
- for (int i = 0; i < files.size(); i++) {
- // Collect all (descriptor, filename) pairs.
- map<const void*, string> descs_in_file;
- for (int j = 0; j < files[i]->message_type_count(); j++) {
- const Descriptor* desc = files[i]->message_type(j);
- string filename =
- options.output_dir + "/" + ToFileName(desc->name()) + ".js";
- descs_in_file[desc] = filename;
- }
- for (int j = 0; j < files[i]->enum_type_count(); j++) {
- const EnumDescriptor* desc = files[i]->enum_type(j);
- string filename =
- options.output_dir + "/" + ToFileName(desc->name()) + ".js";
- descs_in_file[desc] = filename;
- }
-
- // For each (descriptor, filename) pair, update the
- // descriptors-by-filename map, and if a previous descriptor was already
- // writing the filename, remove it from the allowed-descriptors set.
- map<const void*, string>::iterator it;
- for (it = descs_in_file.begin(); it != descs_in_file.end(); ++it) {
- const void* desc = it->first;
- const string& filename = it->second;
- if (desc_by_filename.find(filename) != desc_by_filename.end()) {
- if (options.error_on_name_conflict) {
- *error = "Name conflict: file name " + filename +
- " would be generated by two descriptors";
- return false;
- }
- allowed_descs.erase(desc_by_filename[filename]);
- }
- desc_by_filename[filename] = desc;
- allowed_descs.insert(desc);
- }
+ set<const void*> allowed_set;
+ if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) {
+ return false;
}
- // Generate code.
for (int i = 0; i < files.size(); i++) {
const FileDescriptor* file = files[i];
for (int j = 0; j < file->message_type_count(); j++) {
const Descriptor* desc = file->message_type(j);
- if (allowed_descs.find(desc) == allowed_descs.end()) {
+ if (allowed_set.count(desc) == 0) {
continue;
}
- string filename = options.output_dir + "/" +
- ToFileName(desc->name()) + ".js";
+ string filename = GetMessageFileName(options, desc);
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
@@ -2700,7 +2959,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
FindProvidesForMessage(options, &printer, desc, &provided);
GenerateProvides(options, &printer, &provided);
GenerateTestOnly(options, &printer);
- GenerateRequires(options, &printer, desc, &provided);
+ GenerateRequiresForMessage(options, &printer, desc, &provided);
GenerateClass(options, &printer, desc);
@@ -2710,13 +2969,11 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
}
for (int j = 0; j < file->enum_type_count(); j++) {
const EnumDescriptor* enumdesc = file->enum_type(j);
- if (allowed_descs.find(enumdesc) == allowed_descs.end()) {
+ if (allowed_set.count(enumdesc) == 0) {
continue;
}
- string filename = options.output_dir + "/" +
- ToFileName(enumdesc->name()) + ".js";
-
+ string filename = GetEnumFileName(options, enumdesc);
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
@@ -2735,38 +2992,36 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
return false;
}
}
- // Pull out all free-floating extensions and generate files for those too.
- for (int j = 0; j < file->extension_count(); j++) {
- const FieldDescriptor* extension = file->extension(j);
- extensions_by_namespace[GetPath(options, files[i])]
- .push_back(extension);
- }
- }
+ // File-level extensions (message-level extensions are generated under
+ // the enclosing message).
+ if (allowed_set.count(file) == 1) {
+ string filename = GetExtensionFileName(options, file);
- // Generate extensions in separate files.
- map< string, vector<const FieldDescriptor*> >::iterator it;
- for (it = extensions_by_namespace.begin();
- it != extensions_by_namespace.end();
- ++it) {
- string filename = options.output_dir + "/" +
- ToFileName(it->first) + ".js";
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ io::Printer printer(output.get(), '$');
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
- context->Open(filename));
- GOOGLE_CHECK(output.get());
- io::Printer printer(output.get(), '$');
+ GenerateHeader(options, &printer);
+
+ std::set<string> provided;
+ vector<const FieldDescriptor*> fields;
- GenerateHeader(options, &printer);
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ if (ShouldGenerateExtension(files[i]->extension(j))) {
+ fields.push_back(files[i]->extension(j));
+ }
+ }
- std::set<string> provided;
- FindProvidesForFields(options, &printer, it->second, &provided);
- GenerateProvides(options, &printer, &provided);
- GenerateTestOnly(options, &printer);
- GenerateRequires(options, &printer, it->second, &provided);
+ FindProvidesForFields(options, &printer, fields, &provided);
+ GenerateProvides(options, &printer, &provided);
+ GenerateTestOnly(options, &printer);
+ GenerateRequiresForExtensions(options, &printer, fields, &provided);
- for (int j = 0; j < it->second.size(); j++) {
- if (ShouldGenerateExtension(it->second[j])) {
- GenerateExtension(options, &printer, it->second[j]);
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ if (ShouldGenerateExtension(files[i]->extension(j))) {
+ GenerateExtension(options, &printer, files[i]->extension(j));
+ }
}
}
}
@@ -2777,8 +3032,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
const google::protobuf::FileDescriptor* file = files[i];
string filename = options.output_dir + "/" + GetJSFilename(file->name());
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
- context->Open(filename));
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index db9178d3..6fd7ca50 100755
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -146,19 +146,19 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
io::Printer* printer) const;
// Generate goog.requires() calls.
- void GenerateRequires(const GeneratorOptions& options,
- io::Printer* printer,
- const vector<const FileDescriptor*>& file,
- std::set<string>* provided) const;
- void GenerateRequires(const GeneratorOptions& options,
+ void GenerateRequiresForLibrary(const GeneratorOptions& options,
+ io::Printer* printer,
+ const vector<const FileDescriptor*>& files,
+ std::set<string>* provided) const;
+ void GenerateRequiresForMessage(const GeneratorOptions& options,
io::Printer* printer,
const Descriptor* desc,
std::set<string>* provided) const;
// For extension fields at file scope.
- void GenerateRequires(const GeneratorOptions& options,
- io::Printer* printer,
- const vector<const FieldDescriptor*>& fields,
- std::set<string>* provided) const;
+ void GenerateRequiresForExtensions(
+ const GeneratorOptions& options, io::Printer* printer,
+ const vector<const FieldDescriptor*>& fields,
+ std::set<string>* provided) const;
void GenerateRequiresImpl(const GeneratorOptions& options,
io::Printer* printer,
std::set<string>* required,
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 121d917b..82bb3427 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -32,20 +32,26 @@
#include <google/protobuf/compiler/mock_code_generator.h>
+#include <stdlib.h>
+#include <iostream>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <vector>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 8c8348d8..e1665f88 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -34,10 +34,15 @@
#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
#include <string>
+
#include <google/protobuf/compiler/code_generator.h>
namespace google {
namespace protobuf {
+class FileDescriptor;
+} // namespace protobuf
+
+namespace protobuf {
namespace compiler {
// A mock CodeGenerator, used by command_line_interface_unittest. This is in
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
index 857d24a4..e76f8e99 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -72,8 +72,9 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
"\n",
"name", name_);
- printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
+ printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
"comments", enum_comments,
+ "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_),
"name", name_);
printer->Indent();
@@ -99,8 +100,9 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
}
printer->Print(
- "$name$ = $value$,\n",
+ "$name$$deprecated_attribute$ = $value$,\n",
"name", EnumValueName(all_values_[i]),
+ "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
"value", SimpleItoa(all_values_[i]->number()));
}
printer->Outdent();
@@ -122,16 +124,6 @@ void EnumGenerator::GenerateSource(io::Printer* printer) {
"\n",
"name", name_);
- printer->Print(
- "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
- " static GPBEnumDescriptor *descriptor = NULL;\n"
- " if (!descriptor) {\n"
- " static GPBMessageEnumValueDescription values[] = {\n",
- "name", name_);
- printer->Indent();
- printer->Indent();
- printer->Indent();
-
// Note: For the TextFormat decode info, we can't use the enum value as
// the key because protocol buffer enums have 'allow_alias', which lets
// a value be used more than once. Instead, the index into the list of
@@ -139,41 +131,66 @@ void EnumGenerator::GenerateSource(io::Printer* printer) {
// will be zero.
TextFormatDecodeData text_format_decode_data;
int enum_value_description_key = -1;
+ string text_blob;
for (int i = 0; i < all_values_.size(); i++) {
++enum_value_description_key;
string short_name(EnumValueShortName(all_values_[i]));
- printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
- "short_name", short_name,
- "name", EnumValueName(all_values_[i]));
+ 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->Outdent();
- printer->Outdent();
- printer->Outdent();
+
+ printer->Print(
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+ " static GPBEnumDescriptor *descriptor = NULL;\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(
- " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
- " values:values\n"
- " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
- " enumVerifier:$name$_IsValidValue];\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",
"name", name_);
} else {
printer->Print(
" static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
- " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
- " values:values\n"
- " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
- " enumVerifier:$name$_IsValidValue\n"
- " extraTextFormatInfo:extraTextFormatInfo];\n",
+ " 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(
+ " if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {\n"
+ " [worker release];\n"
+ " }\n"
" }\n"
" return descriptor;\n"
"}\n\n");
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index cfbb8c52..b63bc0de 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -59,6 +59,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*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);
}
@@ -72,13 +75,6 @@ EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
EnumFieldGenerator::~EnumFieldGenerator() {}
-void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
-}
-
void EnumFieldGenerator::GenerateCFunctionDeclarations(
io::Printer* printer) const {
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
@@ -145,13 +141,6 @@ void RepeatedEnumFieldGenerator::FinishInitialization(void) {
"// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
}
-void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
-}
-
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index ae2f57e3..946faa81 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -45,7 +45,6 @@ class EnumFieldGenerator : public SingleFieldGenerator {
const Options& options);
public:
- virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
@@ -64,7 +63,6 @@ class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
public:
virtual void FinishInitialization();
- virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
protected:
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 4e348393..3f7ab9d3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -114,14 +114,14 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
printer->Print(vars,
"{\n"
+ " .defaultValue.$default_name$ = $default$,\n"
" .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
- " .dataType = $extension_type$,\n"
" .extendedClass = GPBStringifySymbol($extended_type$),\n"
- " .fieldNumber = $number$,\n"
- " .defaultValue.$default_name$ = $default$,\n"
" .messageOrGroupClassName = $type$,\n"
- " .options = $options$,\n"
" .enumDescriptorFunc = $enum_desc_func_name$,\n"
+ " .fieldNumber = $number$,\n"
+ " .dataType = $extension_type$,\n"
+ " .options = $options$,\n"
"},\n");
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 8697e225..66cb4a16 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -28,6 +28,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <iostream>
+
#include <google/protobuf/compiler/objectivec/objectivec_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
@@ -75,8 +77,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["field_number_name"] =
classname + "_FieldNumber_" + capitalized_name;
(*variables)["field_number"] = SimpleItoa(descriptor->number());
- (*variables)["has_index"] = SimpleItoa(descriptor->index());
(*variables)["field_type"] = GetCapitalizedType(descriptor);
+ (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
std::vector<string> field_flags;
if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
@@ -99,18 +101,9 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["dataTypeSpecific_name"] = "className";
(*variables)["dataTypeSpecific_value"] = "NULL";
- string field_options = descriptor->options().SerializeAsString();
- // Must convert to a standard byte order for packing length into
- // a cstring.
- uint32 length = ghtonl(field_options.length());
- if (length > 0) {
- string bytes((const char*)&length, sizeof(length));
- bytes.append(field_options);
- string options_str = "\"" + CEscape(bytes) + "\"";
- (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
- } else {
- (*variables)["fieldoptions"] = "";
- }
+ (*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"] = "";
@@ -190,52 +183,54 @@ void FieldGenerator::DetermineForwardDeclarations(
}
void FieldGenerator::GenerateFieldDescription(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- "{\n"
- " .name = \"$name$\",\n"
- " .number = $field_number_name$,\n"
- " .hasIndex = $has_index$,\n"
- " .flags = $fieldflags$,\n"
- " .dataType = GPBDataType$field_type$,\n"
- " .offset = offsetof($classname$__storage_, $name$),\n"
- " .defaultValue.$default_name$ = $default$,\n");
-
- // TODO(thomasvl): It might be useful to add a CPP wrapper to support
- // compiling away the EnumDescriptors. To do that, we'd need a #if here
- // to control setting the descriptor vs. the validator, and above in
- // SetCommonFieldVariables() we'd want to wrap how we add
- // GPBFieldHasDefaultValue to the flags.
-
- // " .dataTypeSpecific.value* = [something],"
- GenerateFieldDescriptionTypeSpecific(printer);
-
- const string& field_options(variables_.find("fieldoptions")->second);
- if (field_options.empty()) {
- printer->Print(" .fieldOptions = NULL,\n");
+ 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 {
- // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
- // outdented because the need for indent captured on the previous
- // printing of a \n and there is no way to get the current indent level
- // to call the right number of Outdent()/Indents() to maintain state.
printer->Print(
variables_,
- "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
- " .fieldOptions = $fieldoptions$,\n"
- "#else\n"
- " .fieldOptions = NULL,\n"
- "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+ "{\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");
}
+}
- printer->Print("},\n");
+void FieldGenerator::SetRuntimeHasBit(int has_index) {
+ variables_["has_index"] = SimpleItoa(has_index);
}
-void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
+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.
+ cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
+ cerr.flush();
+ abort();
}
void FieldGenerator::SetOneofIndexBase(int index_base) {
@@ -272,12 +267,12 @@ void SingleFieldGenerator::GeneratePropertyDeclaration(
printer->Print(variables_, "$comments$");
printer->Print(
variables_,
- "@property(nonatomic, readwrite) $property_type$ $name$;\n"
+ "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
"\n");
if (WantsHasProperty()) {
printer->Print(
variables_,
- "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
}
}
@@ -302,6 +297,14 @@ bool SingleFieldGenerator::WantsHasProperty(void) const {
return false;
}
+bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // The oneof tracks what is set instead.
+ return false;
+ }
+ return true;
+}
+
ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: SingleFieldGenerator(descriptor, options) {
@@ -328,18 +331,18 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
printer->Print(variables_, "$comments$");
printer->Print(
variables_,
- "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
+ "@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$;\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;\n");
+ "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
}
printer->Print("\n");
}
@@ -347,8 +350,6 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
RepeatedFieldGenerator::RepeatedFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: ObjCObjFieldGenerator(descriptor, options) {
- // Repeated fields don't use the has index.
- variables_["has_index"] = "GPBNoHasBit";
// Default to no comment and let the cases needing it fill it in.
variables_["array_comment"] = "";
}
@@ -385,14 +386,14 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
variables_,
"$comments$"
"$array_comment$"
- "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n"
+ "@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;\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;\n");
+ "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
}
printer->Print("\n");
}
@@ -402,6 +403,10 @@ bool RepeatedFieldGenerator::WantsHasProperty(void) const {
return false;
}
+bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+ return false; // The array having anything is what is used.
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
@@ -432,12 +437,40 @@ 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
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index e8a20a72..a3a4b1b6 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -61,7 +61,6 @@ class FieldGenerator {
// Called by GenerateFieldDescription, exposed for classes that need custom
// generation.
- virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
// Exposed for subclasses to extend, base does nothing.
virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
@@ -71,9 +70,16 @@ class FieldGenerator {
virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
// Used during generation, not intended to be extended by subclasses.
- void GenerateFieldDescription(io::Printer* printer) const;
+ 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);
string variable(const char* key) const {
@@ -109,6 +115,8 @@ class SingleFieldGenerator : public FieldGenerator {
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+ virtual bool RuntimeUsesHasBit(void) const;
+
protected:
SingleFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
@@ -143,6 +151,8 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+ virtual bool RuntimeUsesHasBit(void) const;
+
protected:
RepeatedFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
@@ -162,8 +172,14 @@ class FieldGeneratorMap {
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_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 16199884..ed4fc6a3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -45,7 +45,7 @@ namespace protobuf {
// This is also found in GPBBootstrap.h, and needs to be kept in sync. It
// is the version check done to ensure generated code works with the current
// runtime being used.
-const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000;
+const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
namespace compiler {
namespace objectivec {
@@ -115,6 +115,9 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
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");
@@ -189,6 +192,8 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
"\n"
"CF_EXTERN_C_END\n"
"\n"
+ "#pragma clang diagnostic pop\n"
+ "\n"
"// @@protoc_insertion_point(global_scope)\n");
}
@@ -216,6 +221,9 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
}
printer->Print(
"// @@protoc_insertion_point(imports)\n"
+ "\n"
+ "#pragma clang diagnostic push\n"
+ "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
"\n");
printer->Print(
@@ -343,6 +351,8 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Print(
"\n"
+ "#pragma clang diagnostic pop\n"
+ "\n"
"// @@protoc_insertion_point(global_scope)\n");
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 613a511c..196b39dd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -220,11 +220,6 @@ string NameFromFieldDescriptor(const FieldDescriptor* field) {
}
}
-// Escape C++ trigraphs by escaping question marks to \?
-string EscapeTrigraphs(const string& to_escape) {
- return StringReplace(to_escape, "?", "\\?", true);
-}
-
void PathSplit(const string& path, string* directory, string* basename) {
string::size_type last_slash = path.rfind('/');
if (last_slash == string::npos) {
@@ -264,6 +259,11 @@ bool IsSpecialName(const string& name, const string* special_names,
} // namespace
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+ return StringReplace(to_escape, "?", "\\?", true);
+}
+
string StripProto(const string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
@@ -734,7 +734,7 @@ string DefaultValue(const FieldDescriptor* field) {
uint32 length = ghtonl(default_string.length());
string bytes((const char*)&length, sizeof(length));
bytes.append(default_string);
- return "(NSData*)\"" + CEscape(bytes) + "\"";
+ return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
} else {
return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
}
@@ -751,6 +751,51 @@ string DefaultValue(const FieldDescriptor* field) {
return NULL;
}
+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 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;
+}
+
string BuildFlagsString(const vector<string>& strings) {
if (strings.size() == 0) {
return "0";
@@ -969,7 +1014,8 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
} else {
// ...it didn't match!
*out_error = "error: Expected 'option objc_class_prefix = \"" +
- package_match->second + "\";' in '" + file->name() + "'";
+ package_match->second + "\";' for package '" + package +
+ "' in '" + file->name() + "'";
if (prefix.length()) {
*out_error += "; but found '" + prefix + "' instead";
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index a301493e..3f56d94b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -48,6 +48,9 @@ struct Options {
string expected_prefixes_path;
};
+// Escape C++ trigraphs by escaping question marks to "\?".
+string EscapeTrigraphs(const string& to_escape);
+
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
@@ -130,6 +133,22 @@ enum ObjectiveCType {
OBJECTIVECTYPE_MESSAGE
};
+template<class TDescriptor>
+string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) {
+ if (descriptor->options().deprecated()) {
+ string result = "DEPRECATED_ATTRIBUTE";
+ if (preSpace) {
+ result.insert(0, " ");
+ }
+ if (postNewline) {
+ result.append("\n");
+ }
+ return result;
+ } else {
+ return "";
+ }
+}
+
string GetCapitalizedType(const FieldDescriptor* field);
ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
@@ -143,6 +162,7 @@ bool IsReferenceType(const FieldDescriptor* field);
string GPBGenericValueFieldName(const FieldDescriptor* field);
string DefaultValue(const FieldDescriptor* field);
+bool HasNonZeroDefaultValue(const FieldDescriptor* field);
string BuildFlagsString(const vector<string>& strings);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 2751e936..ac5d8aea 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -140,13 +140,18 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
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 suport in RepeatedFieldGenerator to output what the
+ // 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");
@@ -156,13 +161,6 @@ void MapFieldGenerator::FinishInitialization(void) {
}
}
-void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
- io::Printer* printer) const {
- // Relay it to the value generator to provide enum validator, message
- // class, etc.
- value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
-}
-
void MapFieldGenerator::DetermineForwardDeclarations(
set<string>* fwd_decls) const {
RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index 7351ea05..bc68a682 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -46,7 +46,6 @@ class MapFieldGenerator : public RepeatedFieldGenerator {
public:
virtual void FinishInitialization(void);
- virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
protected:
MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index e0ea8bd2..bf272596 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -66,11 +66,12 @@ int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
// The first item in the object structure is our uint32[] for has bits.
// We then want to order things to make the instances as small as
// possible. So we follow the has bits with:
- // 1. Bools (1 byte)
- // 2. Anything always 4 bytes - float, *32, enums
- // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit
+ // 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.
- // 4. Anything always 8 bytes - double, *64
+ // 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
@@ -115,9 +116,9 @@ int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
case FieldDescriptor::TYPE_ENUM:
return 2;
- // 1 byte.
+ // 0 bytes. Stored in the has bits.
case FieldDescriptor::TYPE_BOOL:
- return 1;
+ return 99; // End of the list (doesn't really matter).
}
// Some compilers report reaching end of function even though all cases of
@@ -320,8 +321,9 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
}
printer->Print(
- "$comments$@interface $classname$ : GPBMessage\n\n",
+ "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
"classname", class_name_,
+ "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, false, true),
"comments", message_comments);
vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
@@ -404,32 +406,28 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
sort(sorted_extensions.begin(), sorted_extensions.end(),
ExtensionRangeOrdering());
- // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
- // follows:
- // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
- // to the field's index in the list of fields.
- // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
- // GPBNoHasBit because repeated fields & map<> fields don't use the has
- // bit.
- // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
- // index that groups all the elements on of the oneof.
- // So in has_storage, we need enough bits for the single fields that aren't
- // in any oneof, and then one int32 for each oneof (to store the field
- // number). So we could save a little space by not using the field's index
- // and instead make a second pass only assigning indexes for the fields
- // that would need it. The only savings would come when messages have over
- // a multiple of 32 fields with some number being repeated or in oneofs to
- // drop the count below that 32 multiple; so it hasn't seemed worth doing
- // at the moment.
- size_t num_has_bits = descriptor_->field_count();
+ // 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 (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
iter != oneof_generators_.end(); ++iter) {
(*iter)->SetOneofIndexBase(sizeof_has_storage);
}
field_generators_.SetOneofIndexBase(sizeof_has_storage);
- // Add an int32 for each oneof to store which is set.
+ // sizeof_has_storage 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 += descriptor_->oneof_decl_count();
printer->Print(
@@ -456,47 +454,26 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" static GPBDescriptor *descriptor = nil;\n"
" if (!descriptor) {\n");
- bool has_oneofs = oneof_generators_.size();
- if (has_oneofs) {
- printer->Print(
- " static GPBMessageOneofDescription oneofs[] = {\n");
- printer->Indent();
- printer->Indent();
- printer->Indent();
- for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
- iter != oneof_generators_.end(); ++iter) {
- (*iter)->GenerateDescription(printer);
- }
- printer->Outdent();
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " };\n");
- }
-
TextFormatDecodeData text_format_decode_data;
bool has_fields = descriptor_->field_count() > 0;
+ bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+ string field_description_type;
+ if (need_defaults) {
+ field_description_type = "GPBMessageFieldDescriptionWithDefault";
+ } else {
+ field_description_type = "GPBMessageFieldDescription";
+ }
if (has_fields) {
- // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
- // wraps the fieldOptions's value of this structure in an CPP gate so
- // they can be compiled away; but that still results in a const char* in
- // the structure for a NULL pointer for every message field. If the
- // fieldOptions are moved to a separate payload like the TextFormat extra
- // data is, then it would shrink that static data shrinking the binaries
- // a little more.
- // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
- // structure because primitive types are always zero. If we add a second
- // structure and a different initializer, we can avoid the wasted static
- // storage for every field in a proto3 message.
printer->Print(
- " static GPBMessageFieldDescription fields[] = {\n");
+ " static $field_description_type$ fields[] = {\n",
+ "field_description_type", field_description_type);
printer->Indent();
printer->Indent();
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); ++i) {
const FieldGenerator& field_generator =
field_generators_.get(sorted_fields[i]);
- field_generator.GenerateFieldDescription(printer);
+ 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(),
@@ -510,111 +487,89 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" };\n");
}
- bool has_enums = enum_generators_.size();
- if (has_enums) {
+ map<string, 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<string> init_flags;
+ 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(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_.size() != 0) {
printer->Print(
- " static GPBMessageEnumDescription enums[] = {\n");
- printer->Indent();
- printer->Indent();
- printer->Indent();
- for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
- iter != enum_generators_.end(); ++iter) {
- printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
- "name", (*iter)->name());
+ " static const char *oneofs[] = {\n");
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ printer->Print(
+ " \"$name$\",\n",
+ "name", (*iter)->DescriptorName());
}
- printer->Outdent();
- printer->Outdent();
- printer->Outdent();
printer->Print(
- " };\n");
+ " };\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());
}
-
- bool has_extensions = sorted_extensions.size();
- if (has_extensions) {
+ if (text_format_decode_data.num_entries() != 0) {
+ const string text_format_data_str(text_format_decode_data.Data());
printer->Print(
- " static GPBExtensionRange ranges[] = {\n");
- printer->Indent();
- printer->Indent();
- printer->Indent();
- for (int i = 0; i < sorted_extensions.size(); i++) {
- printer->Print("{ .start = $start$, .end = $end$ },\n",
- "start", SimpleItoa(sorted_extensions[i]->start),
- "end", SimpleItoa(sorted_extensions[i]->end));
+ "#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->Outdent();
- printer->Outdent();
- printer->Outdent();
printer->Print(
- " };\n");
+ ";\n"
+ " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+ "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
}
-
- map<string, string> vars;
- vars["classname"] = class_name_;
- vars["rootclassname"] = root_classname_;
- vars["fields"] = has_fields ? "fields" : "NULL";
- vars["fields_count"] =
- has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
- vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
- vars["oneof_count"] =
- has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
- vars["enums"] = has_enums ? "enums" : "NULL";
- vars["enum_count"] =
- has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
- vars["ranges"] = has_extensions ? "ranges" : "NULL";
- vars["range_count"] =
- has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
- vars["wireformat"] =
- descriptor_->options().message_set_wire_format() ? "YES" : "NO";
-
- if (text_format_decode_data.num_entries() == 0) {
+ if (sorted_extensions.size() != 0) {
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"
- " oneofs:$oneofs$\n"
- " oneofCount:$oneof_count$\n"
- " enums:$enums$\n"
- " enumCount:$enum_count$\n"
- " ranges:$ranges$\n"
- " rangeCount:$range_count$\n"
- " storageSize:sizeof($classname$__storage_)\n"
- " wireFormat:$wireformat$];\n");
- } else {
- vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
- printer->Print(
- vars,
- "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
- " const char *extraTextFormatInfo = NULL;\n"
- "#else\n"
- " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
- "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
- " GPBDescriptor *localDescriptor =\n"
- " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
- " rootClass:[$rootclassname$ class]\n"
- " file:$rootclassname$_FileDescriptor()\n"
- " fields:$fields$\n"
- " fieldCount:$fields_count$\n"
- " oneofs:$oneofs$\n"
- " oneofCount:$oneof_count$\n"
- " enums:$enums$\n"
- " enumCount:$enum_count$\n"
- " ranges:$ranges$\n"
- " rangeCount:$range_count$\n"
- " storageSize:sizeof($classname$__storage_)\n"
- " wireFormat:$wireformat$\n"
- " extraTextFormatInfo:extraTextFormatInfo];\n");
+ " static const GPBExtensionRange ranges[] = {\n");
+ for (int i = 0; i < sorted_extensions.size(); i++) {
+ printer->Print(" { .start = $start$, .end = $end$ },\n",
+ "start", SimpleItoa(sorted_extensions[i]->start),
+ "end", SimpleItoa(sorted_extensions[i]->end));
}
printer->Print(
- " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
- " descriptor = localDescriptor;\n"
- " }\n"
- " return descriptor;\n"
- "}\n\n"
- "@end\n\n");
+ " };\n"
+ " [localDescriptor setupExtensionRanges:ranges\n"
+ " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+ }
+ printer->Print(
+ " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+ " descriptor = localDescriptor;\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n"
+ "@end\n\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
index 24e6df07..44bafd7f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -120,17 +120,16 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
" GPBDescriptor *descriptor = [message descriptor];\n"
" GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
- " GPBMaybeClearOneof(message, oneof, 0);\n"
+ " GPBMaybeClearOneof(message, oneof, $index$, 0);\n"
"}\n");
}
-void OneofGenerator::GenerateDescription(io::Printer* printer) {
- printer->Print(
- variables_,
- "{\n"
- " .name = \"$name$\",\n"
- " .index = $index$,\n"
- "},\n");
+string OneofGenerator::DescriptorName(void) const {
+ return variables_.find("name")->second;
+}
+
+string OneofGenerator::HasIndexAsString(void) const {
+ return variables_.find("index")->second;
}
} // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
index bcba82da..3d9df4db 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -61,7 +61,9 @@ class OneofGenerator {
void GeneratePropertyImplementation(io::Printer* printer);
void GenerateClearFunctionImplementation(io::Printer* printer);
- void GenerateDescription(io::Printer* printer);
+
+ string DescriptorName(void) const;
+ string HasIndexAsString(void) const;
private:
const OneofDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index ea7f1b91..d49350f4 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -134,6 +134,32 @@ PrimitiveFieldGenerator::PrimitiveFieldGenerator(
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"] = SimpleItoa(has_base);
+ variables_["storage_offset_comment"] =
+ " // Stored in _has_storage_ to save space.";
+ }
+}
+
PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: ObjCObjFieldGenerator(descriptor, options) {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
index 87139afb..69bb1fdd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -49,6 +49,11 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator {
const Options& options);
virtual ~PrimitiveFieldGenerator();
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+
+ virtual int ExtraRuntimeHasBitsNeeded(void) const;
+ virtual void SetExtraRuntimeHasBitsBase(int index_base);
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
};
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 2bebf1f3..2ff50f61 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -93,31 +93,15 @@ class GeneratorResponseContext : public GeneratorContext {
const vector<const FileDescriptor*>& parsed_files_;
};
-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;
- }
-
+bool GenerateCode(const CodeGeneratorRequest& request,
+ const CodeGenerator& generator, CodeGeneratorResponse* response,
+ 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 1;
+ return false;
}
}
@@ -125,19 +109,18 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
for (int i = 0; i < request.file_to_generate_size(); i++) {
parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
if (parsed_files.back() == NULL) {
- std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
- "did not provide a descriptor for the file: "
- << request.file_to_generate(i) << std::endl;
- return 1;
+ *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;
}
}
- CodeGeneratorResponse response;
- GeneratorResponseContext context(&response, parsed_files);
+ GeneratorResponseContext context(response, parsed_files);
- if (generator->HasGenerateAll()) {
+ if (generator.HasGenerateAll()) {
string error;
- bool succeeded = generator->GenerateAll(
+ bool succeeded = generator.GenerateAll(
parsed_files, request.parameter(), &context, &error);
if (!succeeded && error.empty()) {
@@ -145,14 +128,14 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
"description.";
}
if (!error.empty()) {
- response.set_error(error);
+ response->set_error(error);
}
} else {
for (int i = 0; i < parsed_files.size(); i++) {
const FileDescriptor* file = parsed_files[i];
string error;
- bool succeeded = generator->Generate(
+ bool succeeded = generator.Generate(
file, request.parameter(), &context, &error);
if (!succeeded && error.empty()) {
@@ -160,14 +143,46 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
"description.";
}
if (!error.empty()) {
- response.set_error(file->name() + ": " + error);
+ response->set_error(file->name() + ": " + error);
break;
}
}
}
- if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
- std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+ 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;
+ }
+
+ 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;
}
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 679f9bdb..d2793a9f 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -40,6 +40,13 @@
// }
// 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
@@ -55,16 +62,27 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+#include <string>
+
#include <google/protobuf/stubs/common.h>
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.
LIBPROTOC_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 geneartion fails, error_msg may be
+// populated to describe the failure cause.
+bool GenerateCode(const CodeGeneratorRequest& request,
+ const CodeGenerator& generator, CodeGeneratorResponse* response,
+ string* error_msg);
+
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index a2da8eee..e9d50a1d 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -240,6 +240,7 @@ CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena
}
void CodeGeneratorRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
if (has_parameter()) {
parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -253,7 +254,7 @@ void CodeGeneratorRequest::Clear() {
bool CodeGeneratorRequest::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest)
for (;;) {
@@ -412,6 +413,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
}
int CodeGeneratorRequest::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
int total_size = 0;
// optional string parameter = 2;
@@ -448,18 +450,22 @@ int CodeGeneratorRequest::ByteSize() const {
}
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const CodeGeneratorRequest* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest)
MergeFrom(*source);
}
}
void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
file_to_generate_.MergeFrom(from.file_to_generate_);
proto_file_.MergeFrom(from.proto_file_);
@@ -475,12 +481,14 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
}
void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
if (&from == this) return;
Clear();
MergeFrom(from);
}
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);
@@ -545,6 +553,7 @@ void CodeGeneratorRequest::clear_file_to_generate() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
::std::string* CodeGeneratorRequest::add_file_to_generate() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_.Add();
}
void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
@@ -610,6 +619,7 @@ void CodeGeneratorRequest::clear_parameter() {
return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* CodeGeneratorRequest::release_parameter() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
clear_has_parameter();
return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -728,6 +738,7 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::
}
void CodeGeneratorResponse_File::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
if (_has_bits_[0 / 32] & 7u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -747,7 +758,7 @@ void CodeGeneratorResponse_File::Clear() {
bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File)
for (;;) {
@@ -912,6 +923,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
}
int CodeGeneratorResponse_File::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
int total_size = 0;
if (_has_bits_[0 / 32] & 7u) {
@@ -949,18 +961,22 @@ int CodeGeneratorResponse_File::ByteSize() const {
}
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const CodeGeneratorResponse_File* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File)
MergeFrom(*source);
}
}
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -982,12 +998,14 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro
}
void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
if (&from == this) return;
Clear();
MergeFrom(from);
}
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);
@@ -1088,6 +1106,7 @@ CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* are
}
void CodeGeneratorResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
if (has_error()) {
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1100,7 +1119,7 @@ void CodeGeneratorResponse::Clear() {
bool CodeGeneratorResponse::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse)
for (;;) {
@@ -1219,6 +1238,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
}
int CodeGeneratorResponse::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
int total_size = 0;
// optional string error = 1;
@@ -1248,18 +1268,22 @@ int CodeGeneratorResponse::ByteSize() const {
}
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const CodeGeneratorResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse)
MergeFrom(*source);
}
}
void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
file_.MergeFrom(from.file_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -1274,12 +1298,14 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
}
void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
if (&from == this) return;
Clear();
MergeFrom(from);
}
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);
@@ -1353,6 +1379,7 @@ void CodeGeneratorResponse_File::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* CodeGeneratorResponse_File::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1406,6 +1433,7 @@ void CodeGeneratorResponse_File::clear_insertion_point() {
return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
clear_has_insertion_point();
return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1459,6 +1487,7 @@ void CodeGeneratorResponse_File::clear_content() {
return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* CodeGeneratorResponse_File::release_content() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
clear_has_content();
return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1516,6 +1545,7 @@ void CodeGeneratorResponse::clear_error() {
return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* CodeGeneratorResponse::release_error() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
clear_has_error();
return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 0a03e979..510202f0 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -437,6 +437,7 @@ inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* va
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_.Add();
}
inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
@@ -502,6 +503,7 @@ inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* CodeGeneratorRequest::release_parameter() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
clear_has_parameter();
return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -589,6 +591,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* CodeGeneratorResponse_File::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -642,6 +645,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
clear_has_insertion_point();
return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -695,6 +699,7 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* CodeGeneratorResponse_File::release_content() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
clear_has_content();
return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -752,6 +757,7 @@ inline ::std::string* CodeGeneratorResponse::mutable_error() {
return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* CodeGeneratorResponse::release_error() {
+ // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
clear_has_error();
return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 4d500f90..0553dd0d 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -235,7 +235,7 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
// infinity * 0 = nan
return "(1e10000 * 0)";
} else {
- return SimpleDtoa(value);
+ return "float(" + SimpleDtoa(value) + ")";
}
}
case FieldDescriptor::CPPTYPE_FLOAT: {
@@ -251,7 +251,7 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
// infinity - infinity = nan
return "(1e10000 * 0)";
} else {
- return SimpleFtoa(value);
+ return "float(" + SimpleFtoa(value) + ")";
}
}
case FieldDescriptor::CPPTYPE_BOOL:
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index e82bbae7..23f2449c 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -44,9 +44,10 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index a30ac305..6e258664 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -361,7 +361,7 @@ bool Subprocess::Communicate(const Message& input, Message* output,
string output_data;
int input_pos = 0;
- int max_fd = max(child_stdin_, child_stdout_);
+ int max_fd = std::max(child_stdin_, child_stdout_);
while (child_stdout_ != -1) {
fd_set read_fds;
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 78a34617..56e11fa9 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -357,13 +357,20 @@ void DeleteAllowedProto3Extendee() {
void InitAllowedProto3Extendee() {
allowed_proto3_extendees_ = new set<string>;
- allowed_proto3_extendees_->insert("google.protobuf.FileOptions");
- allowed_proto3_extendees_->insert("google.protobuf.MessageOptions");
- allowed_proto3_extendees_->insert("google.protobuf.FieldOptions");
- allowed_proto3_extendees_->insert("google.protobuf.EnumOptions");
- allowed_proto3_extendees_->insert("google.protobuf.EnumValueOptions");
- allowed_proto3_extendees_->insert("google.protobuf.ServiceOptions");
- allowed_proto3_extendees_->insert("google.protobuf.MethodOptions");
+ const char* kOptionNames[] = {
+ "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions",
+ "EnumValueOptions", "ServiceOptions", "MethodOptions"};
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
+ // descriptor.proto has a different package name in opensource. We allow
+ // both so the opensource protocol compiler can also compile internal
+ // proto3 files with custom options. See: b/27567912
+ allowed_proto3_extendees_->insert(string("google.protobuf.") +
+ kOptionNames[i]);
+ // Split the word to trick the opensource processing scripts so they
+ // will keep the origial package name.
+ allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]);
+ }
+
google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee);
}
@@ -2766,6 +2773,9 @@ class DescriptorBuilder {
private:
friend class OptionInterpreter;
+ // Non-recursive part of BuildFile functionality.
+ const FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto);
+
const DescriptorPool* pool_;
DescriptorPool::Tables* tables_; // for convenience
DescriptorPool::ErrorCollector* error_collector_;
@@ -3834,7 +3844,11 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
}
tables_->pending_files_.pop_back();
}
+ return BuildFileImpl(proto);
+}
+const FileDescriptor* DescriptorBuilder::BuildFileImpl(
+ const FileDescriptorProto& proto) {
// Checkpoint the tables so that we can roll back if something goes wrong.
tables_->AddCheckpoint();
@@ -5113,11 +5127,6 @@ void DescriptorBuilder::ValidateProto3(
for (int i = 0; i < file->enum_type_count(); ++i) {
ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
}
- if (IsLite(file)) {
- AddError(file->name(), proto,
- DescriptorPool::ErrorCollector::OTHER,
- "Lite runtime is not supported in proto3.");
- }
}
static string ToLowercaseWithoutUnderscores(const string& name) {
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 7e3a7496..3ecc0a9c 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -127,6 +127,11 @@ namespace descriptor_unittest {
class DescriptorTest;
} // namespace descriptor_unittest
+// Defined in printer.h
+namespace io {
+class Printer;
+} // namespace io
+
// NB, all indices are zero-based.
struct SourceLocation {
int start_line;
@@ -359,6 +364,9 @@ class LIBPROTOBUF_EXPORT Descriptor {
// Allows tests to test CopyTo(proto, true).
friend class ::google::protobuf::descriptor_unittest::DescriptorTest;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// Fill the json_name field of FieldDescriptorProto.
void CopyJsonNameTo(DescriptorProto* proto) const;
@@ -644,6 +652,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
private:
typedef FieldOptions OptionsType;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// Fill the json_name field of FieldDescriptorProto.
void CopyJsonNameTo(FieldDescriptorProto* proto) const;
@@ -756,6 +767,9 @@ class LIBPROTOBUF_EXPORT OneofDescriptor {
bool GetSourceLocation(SourceLocation* out_location) const;
private:
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// See Descriptor::DebugString().
void DebugString(int depth, string* contents,
const DebugStringOptions& options) const;
@@ -846,6 +860,9 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
private:
typedef EnumOptions OptionsType;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// Looks up a value by number. If the value does not exist, dynamically
// creates a new EnumValueDescriptor for that value, assuming that it was
// unknown. If a new descriptor is created, this is done in a thread-safe way,
@@ -942,6 +959,9 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
private:
typedef EnumValueOptions OptionsType;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// See Descriptor::DebugString().
void DebugString(int depth, string *contents,
const DebugStringOptions& options) const;
@@ -1018,6 +1038,9 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
private:
typedef ServiceOptions OptionsType;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// See Descriptor::DebugString().
void DebugString(string *contents, const DebugStringOptions& options) const;
@@ -1096,6 +1119,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
private:
typedef MethodOptions OptionsType;
+ // Allows access to GetLocationPath for annotations.
+ friend class ::google::protobuf::io::Printer;
+
// See Descriptor::DebugString().
void DebugString(int depth, string *contents,
const DebugStringOptions& options) const;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index ff0cfcf8..4d5c4d99 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -319,7 +319,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
-1);
FileOptions_descriptor_ = file->message_type(9);
- static const int FileOptions_offsets_[16] = {
+ static const int FileOptions_offsets_[15] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
@@ -334,7 +334,6 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, javanano_use_deprecated_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
};
FileOptions_reflection_ =
@@ -746,7 +745,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
"otobuf.MethodOptions\022\037\n\020client_streaming"
"\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010:"
- "\005false\"\256\005\n\013FileOptions\022\024\n\014java_package\030\001"
+ "\005false\"\207\005\n\013FileOptions\022\024\n\014java_package\030\001"
" \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
"va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
"enerate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026"
@@ -758,60 +757,59 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"e\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n"
"\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_ar"
"enas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030$"
- " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022+\n\037javana"
- "no_use_deprecated_package\030& \001(\010B\002\030\001\022C\n\024u"
- "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
- "obuf.UninterpretedOption\":\n\014OptimizeMode"
- "\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTI"
- "ME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027me"
- "ssage_set_wire_format\030\001 \001(\010:\005false\022.\n\037no"
- "_standard_descriptor_accessor\030\002 \001(\010:\005fal"
- "se\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_ent"
- "ry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
- "$.google.protobuf.UninterpretedOption*\t\010"
- "\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\016"
- "2#.google.protobuf.FieldOptions.CType:\006S"
- "TRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$."
- "google.protobuf.FieldOptions.JSType:\tJS_"
- "NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecate"
- "d\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
- "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
- "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
- "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JST"
- "ype\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_"
- "NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013a"
- "llow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fa"
- "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
- "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
- "\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 "
- "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003("
- "\0132$.google.protobuf.UninterpretedOption*"
- "\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecat"
- "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
- "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
- "tion*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndepr"
- "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
- "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
- "edOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOpt"
- "ion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Unin"
- "terpretedOption.NamePart\022\030\n\020identifier_v"
- "alue\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032"
- "\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_val"
- "ue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggreg"
- "ate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part"
- "\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceC"
- "odeInfo\022:\n\010location\030\001 \003(\0132(.google.proto"
- "buf.SourceCodeInfo.Location\032\206\001\n\010Location"
- "\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020"
- "leading_comments\030\003 \001(\t\022\031\n\021trailing_comme"
- "nts\030\004 \001(\t\022!\n\031leading_detached_comments\030\006"
- " \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotation"
- "\030\001 \003(\0132-.google.protobuf.GeneratedCodeIn"
- "fo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003("
- "\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001("
- "\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020D"
- "escriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032Go"
- "ogle.Protobuf.Reflection", 5184);
+ " \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024uninte"
+ "rpreted_option\030\347\007 \003(\0132$.google.protobuf."
+ "UninterpretedOption\":\n\014OptimizeMode\022\t\n\005S"
+ "PEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*"
+ "\t\010\350\007\020\200\200\200\200\002J\004\010&\020\'\"\346\001\n\016MessageOptions\022&\n\027m"
+ "essage_set_wire_format\030\001 \001(\010:\005false\022.\n\037n"
+ "o_standard_descriptor_accessor\030\002 \001(\010:\005fa"
+ "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_en"
+ "try\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\013"
+ "2$.google.protobuf.UninterpretedOption*\t"
+ "\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001("
+ "\0162#.google.protobuf.FieldOptions.CType:\006"
+ "STRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$"
+ ".google.protobuf.FieldOptions.JSType:\tJS"
+ "_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecat"
+ "ed\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024"
+ "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+ "tobuf.UninterpretedOption\"/\n\005CType\022\n\n\006ST"
+ "RING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JS"
+ "Type\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS"
+ "_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013"
+ "allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f"
+ "alse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+ "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+ "\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001"
+ " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+ "(\0132$.google.protobuf.UninterpretedOption"
+ "*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndepreca"
+ "ted\030! \001(\010:\005false\022C\n\024uninterpreted_option"
+ "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
+ "ption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndep"
+ "recated\030! \001(\010:\005false\022C\n\024uninterpreted_op"
+ "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+ "tedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOp"
+ "tion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Uni"
+ "nterpretedOption.NamePart\022\030\n\020identifier_"
+ "value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022"
+ "\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_va"
+ "lue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggre"
+ "gate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_par"
+ "t\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016Source"
+ "CodeInfo\022:\n\010location\030\001 \003(\0132(.google.prot"
+ "obuf.SourceCodeInfo.Location\032\206\001\n\010Locatio"
+ "n\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n"
+ "\020leading_comments\030\003 \001(\t\022\031\n\021trailing_comm"
+ "ents\030\004 \001(\t\022!\n\031leading_detached_comments\030"
+ "\006 \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotatio"
+ "n\030\001 \003(\0132-.google.protobuf.GeneratedCodeI"
+ "nfo.Annotation\032O\n\nAnnotation\022\020\n\004path\030\001 \003"
+ "(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001"
+ "(\005\022\013\n\003end\030\004 \001(\005BX\n\023com.google.protobufB\020"
+ "DescriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032G"
+ "oogle.Protobuf.Reflection", 5145);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -946,6 +944,7 @@ FileDescriptorSet* FileDescriptorSet::New(::google::protobuf::Arena* arena) cons
}
void FileDescriptorSet::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
@@ -955,7 +954,7 @@ void FileDescriptorSet::Clear() {
bool FileDescriptorSet::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet)
for (;;) {
@@ -1036,6 +1035,7 @@ void FileDescriptorSet::SerializeWithCachedSizes(
}
int FileDescriptorSet::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet)
int total_size = 0;
// repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -1058,18 +1058,22 @@ int FileDescriptorSet::ByteSize() const {
}
void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FileDescriptorSet* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorSet)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorSet)
MergeFrom(*source);
}
}
void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
file_.MergeFrom(from.file_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -1078,12 +1082,14 @@ void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
}
void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorSet)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorSet)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1237,6 +1243,7 @@ FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena)
}
void FileDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
if (_has_bits_[0 / 32] & 3u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -1271,7 +1278,7 @@ void FileDescriptorProto::Clear() {
bool FileDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto)
for (;;) {
@@ -1706,6 +1713,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
}
int FileDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 3u) {
@@ -1818,18 +1826,22 @@ int FileDescriptorProto::ByteSize() const {
}
void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FileDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorProto)
MergeFrom(*source);
}
}
void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
dependency_.MergeFrom(from.dependency_);
public_dependency_.MergeFrom(from.public_dependency_);
@@ -1866,12 +1878,14 @@ void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
}
void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1962,6 +1976,7 @@ void FileDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2015,6 +2030,7 @@ void FileDescriptorProto::clear_package() {
return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileDescriptorProto::release_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
clear_has_package();
return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2057,6 +2073,7 @@ void FileDescriptorProto::clear_dependency() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
}
::std::string* FileDescriptorProto::add_dependency() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency)
return dependency_.Add();
}
void FileDescriptorProto::add_dependency(const ::std::string& value) {
@@ -2289,6 +2306,7 @@ const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
return options_;
}
::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options)
clear_has_options();
::google::protobuf::FileOptions* temp = options_;
options_ = NULL;
@@ -2332,6 +2350,7 @@ const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info(
return source_code_info_;
}
::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info)
clear_has_source_code_info();
::google::protobuf::SourceCodeInfo* temp = source_code_info_;
source_code_info_ = NULL;
@@ -2388,6 +2407,7 @@ void FileDescriptorProto::clear_syntax() {
return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileDescriptorProto::release_syntax() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
clear_has_syntax();
return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2470,8 +2490,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr
}
void DescriptorProto_ExtensionRange::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(DescriptorProto_ExtensionRange, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -2491,7 +2520,7 @@ void DescriptorProto_ExtensionRange::Clear() {
bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange)
for (;;) {
@@ -2592,6 +2621,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
}
int DescriptorProto_ExtensionRange::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange)
int total_size = 0;
if (_has_bits_[0 / 32] & 3u) {
@@ -2622,18 +2652,22 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
}
void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const DescriptorProto_ExtensionRange* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ExtensionRange)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ExtensionRange)
MergeFrom(*source);
}
}
void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_start()) {
@@ -2649,12 +2683,14 @@ void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRa
}
void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2753,8 +2789,17 @@ DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::prot
}
void DescriptorProto_ReservedRange::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(DescriptorProto_ReservedRange, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -2774,7 +2819,7 @@ void DescriptorProto_ReservedRange::Clear() {
bool DescriptorProto_ReservedRange::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange)
for (;;) {
@@ -2875,6 +2920,7 @@ void DescriptorProto_ReservedRange::SerializeWithCachedSizes(
}
int DescriptorProto_ReservedRange::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange)
int total_size = 0;
if (_has_bits_[0 / 32] & 3u) {
@@ -2905,18 +2951,22 @@ int DescriptorProto_ReservedRange::ByteSize() const {
}
void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const DescriptorProto_ReservedRange* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ReservedRange)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ReservedRange)
MergeFrom(*source);
}
}
void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_start()) {
@@ -2932,12 +2982,14 @@ void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRang
}
void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ReservedRange)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ReservedRange)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -3048,6 +3100,7 @@ DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const {
}
void DescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
if (_has_bits_[0 / 32] & 129u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -3072,7 +3125,7 @@ void DescriptorProto::Clear() {
bool DescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto)
for (;;) {
@@ -3431,6 +3484,7 @@ void DescriptorProto::SerializeWithCachedSizes(
}
int DescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 129u) {
@@ -3524,18 +3578,22 @@ int DescriptorProto::ByteSize() const {
}
void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const DescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto)
MergeFrom(*source);
}
}
void DescriptorProto::MergeFrom(const DescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
field_.MergeFrom(from.field_);
extension_.MergeFrom(from.extension_);
@@ -3560,12 +3618,14 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) {
}
void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void DescriptorProto::CopyFrom(const DescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -3758,6 +3818,7 @@ void DescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* DescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3978,6 +4039,7 @@ const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
return options_;
}
::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options)
clear_has_options();
::google::protobuf::MessageOptions* temp = options_;
options_ = NULL;
@@ -4053,6 +4115,7 @@ void DescriptorProto::clear_reserved_name() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
}
::std::string* DescriptorProto::add_reserved_name() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name)
return reserved_name_.Add();
}
void DescriptorProto::add_reserved_name(const ::std::string& value) {
@@ -4247,6 +4310,7 @@ FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena
}
void FieldDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
if (_has_bits_[0 / 32] & 255u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -4281,7 +4345,7 @@ void FieldDescriptorProto::Clear() {
bool FieldDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto)
for (;;) {
@@ -4662,6 +4726,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
}
int FieldDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 255u) {
@@ -4748,18 +4813,22 @@ int FieldDescriptorProto::ByteSize() const {
}
void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FieldDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldDescriptorProto)
MergeFrom(*source);
}
}
void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -4806,12 +4875,14 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
}
void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -4896,6 +4967,7 @@ void FieldDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5023,6 +5095,7 @@ void FieldDescriptorProto::clear_type_name() {
return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_type_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
clear_has_type_name();
return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5076,6 +5149,7 @@ void FieldDescriptorProto::clear_extendee() {
return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_extendee() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
clear_has_extendee();
return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5129,6 +5203,7 @@ void FieldDescriptorProto::clear_default_value() {
return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_default_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
clear_has_default_value();
return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5206,6 +5281,7 @@ void FieldDescriptorProto::clear_json_name() {
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FieldDescriptorProto::release_json_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
clear_has_json_name();
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5246,6 +5322,7 @@ const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
return options_;
}
::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options)
clear_has_options();
::google::protobuf::FieldOptions* temp = options_;
options_ = NULL;
@@ -5331,6 +5408,7 @@ OneofDescriptorProto* OneofDescriptorProto::New(::google::protobuf::Arena* arena
}
void OneofDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5342,7 +5420,7 @@ void OneofDescriptorProto::Clear() {
bool OneofDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto)
for (;;) {
@@ -5431,6 +5509,7 @@ void OneofDescriptorProto::SerializeWithCachedSizes(
}
int OneofDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto)
int total_size = 0;
// optional string name = 1;
@@ -5452,18 +5531,22 @@ int OneofDescriptorProto::ByteSize() const {
}
void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const OneofDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofDescriptorProto)
MergeFrom(*source);
}
}
void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -5477,12 +5560,14 @@ void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
}
void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.OneofDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -5555,6 +5640,7 @@ void OneofDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* OneofDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5642,6 +5728,7 @@ EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena)
}
void EnumDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
if (_has_bits_[0 / 32] & 5u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -5659,7 +5746,7 @@ void EnumDescriptorProto::Clear() {
bool EnumDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto)
for (;;) {
@@ -5804,6 +5891,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
}
int EnumDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 5u) {
@@ -5842,18 +5930,22 @@ int EnumDescriptorProto::ByteSize() const {
}
void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const EnumDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto)
MergeFrom(*source);
}
}
void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
value_.MergeFrom(from.value_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -5871,12 +5963,14 @@ void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
}
void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -5955,6 +6049,7 @@ void EnumDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* EnumDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6025,6 +6120,7 @@ const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
return options_;
}
::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options)
clear_has_options();
::google::protobuf::EnumOptions* temp = options_;
options_ = NULL;
@@ -6116,6 +6212,7 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Aren
}
void EnumValueDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
if (_has_bits_[0 / 32] & 7u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -6133,7 +6230,7 @@ void EnumValueDescriptorProto::Clear() {
bool EnumValueDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto)
for (;;) {
@@ -6273,6 +6370,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
}
int EnumValueDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 7u) {
@@ -6310,18 +6408,22 @@ int EnumValueDescriptorProto::ByteSize() const {
}
void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const EnumValueDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueDescriptorProto)
MergeFrom(*source);
}
}
void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -6341,12 +6443,14 @@ void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
}
void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -6424,6 +6528,7 @@ void EnumValueDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* EnumValueDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6488,6 +6593,7 @@ const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options()
return options_;
}
::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options)
clear_has_options();
::google::protobuf::EnumValueOptions* temp = options_;
options_ = NULL;
@@ -6578,6 +6684,7 @@ ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* a
}
void ServiceDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
if (_has_bits_[0 / 32] & 5u) {
if (has_name()) {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -6595,7 +6702,7 @@ void ServiceDescriptorProto::Clear() {
bool ServiceDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto)
for (;;) {
@@ -6740,6 +6847,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
}
int ServiceDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 5u) {
@@ -6778,18 +6886,22 @@ int ServiceDescriptorProto::ByteSize() const {
}
void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const ServiceDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceDescriptorProto)
MergeFrom(*source);
}
}
void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
method_.MergeFrom(from.method_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -6807,12 +6919,14 @@ void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
}
void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -6891,6 +7005,7 @@ void ServiceDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* ServiceDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6961,6 +7076,7 @@ const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() cons
return options_;
}
::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options)
clear_has_options();
::google::protobuf::ServiceOptions* temp = options_;
options_ = NULL;
@@ -7060,8 +7176,17 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are
}
void MethodDescriptorProto::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(MethodDescriptorProto, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<MethodDescriptorProto*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -7095,7 +7220,7 @@ void MethodDescriptorProto::Clear() {
bool MethodDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto)
for (;;) {
@@ -7336,6 +7461,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
}
int MethodDescriptorProto::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto)
int total_size = 0;
if (_has_bits_[0 / 32] & 63u) {
@@ -7390,18 +7516,22 @@ int MethodDescriptorProto::ByteSize() const {
}
void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const MethodDescriptorProto* source =
::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodDescriptorProto)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodDescriptorProto)
MergeFrom(*source);
}
}
void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
@@ -7432,12 +7562,14 @@ void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
}
void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodDescriptorProto)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -7518,6 +7650,7 @@ void MethodDescriptorProto::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* MethodDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7571,6 +7704,7 @@ void MethodDescriptorProto::clear_input_type() {
return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* MethodDescriptorProto::release_input_type() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
clear_has_input_type();
return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7624,6 +7758,7 @@ void MethodDescriptorProto::clear_output_type() {
return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* MethodDescriptorProto::release_output_type() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
clear_has_output_type();
return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7664,6 +7799,7 @@ const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const
return options_;
}
::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options)
clear_has_options();
::google::protobuf::MethodOptions* temp = options_;
options_ = NULL;
@@ -7770,7 +7906,6 @@ const int FileOptions::kDeprecatedFieldNumber;
const int FileOptions::kCcEnableArenasFieldNumber;
const int FileOptions::kObjcClassPrefixFieldNumber;
const int FileOptions::kCsharpNamespaceFieldNumber;
-const int FileOptions::kJavananoUseDeprecatedPackageFieldNumber;
const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -7808,7 +7943,6 @@ void FileOptions::SharedCtor() {
cc_enable_arenas_ = false;
objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- javanano_use_deprecated_package_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -7853,9 +7987,18 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const {
}
void FileOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
_extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(FileOptions, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<FileOptions*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -7875,8 +8018,8 @@ void FileOptions::Clear() {
go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
}
- if (_has_bits_[8 / 32] & 32512u) {
- ZR_(java_generic_services_, javanano_use_deprecated_package_);
+ if (_has_bits_[8 / 32] & 16128u) {
+ ZR_(java_generic_services_, cc_enable_arenas_);
if (has_objc_class_prefix()) {
objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7897,7 +8040,7 @@ void FileOptions::Clear() {
bool FileOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FileOptions)
for (;;) {
@@ -8125,21 +8268,6 @@ bool FileOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
- if (input->ExpectTag(304)) goto parse_javanano_use_deprecated_package;
- break;
- }
-
- // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
- case 38: {
- if (tag == 304) {
- parse_javanano_use_deprecated_package:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
- input, &javanano_use_deprecated_package_)));
- set_has_javanano_use_deprecated_package();
- } else {
- goto handle_unusual;
- }
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
@@ -8287,11 +8415,6 @@ void FileOptions::SerializeWithCachedSizes(
37, this->csharp_namespace(), output);
}
- // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
- if (has_javanano_use_deprecated_package()) {
- ::google::protobuf::internal::WireFormatLite::WriteBool(38, this->javanano_use_deprecated_package(), output);
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -8413,11 +8536,6 @@ void FileOptions::SerializeWithCachedSizes(
37, this->csharp_namespace(), target);
}
- // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
- if (has_javanano_use_deprecated_package()) {
- target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(38, this->javanano_use_deprecated_package(), target);
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
target = ::google::protobuf::internal::WireFormatLite::
@@ -8438,6 +8556,7 @@ void FileOptions::SerializeWithCachedSizes(
}
int FileOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions)
int total_size = 0;
if (_has_bits_[0 / 32] & 255u) {
@@ -8489,7 +8608,7 @@ int FileOptions::ByteSize() const {
}
}
- if (_has_bits_[8 / 32] & 32512u) {
+ if (_has_bits_[8 / 32] & 16128u) {
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
total_size += 2 + 1;
@@ -8524,11 +8643,6 @@ int FileOptions::ByteSize() const {
this->csharp_namespace());
}
- // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
- if (has_javanano_use_deprecated_package()) {
- total_size += 2 + 1;
- }
-
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -8552,18 +8666,22 @@ int FileOptions::ByteSize() const {
}
void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FileOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileOptions)
MergeFrom(*source);
}
}
void FileOptions::MergeFrom(const FileOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -8616,9 +8734,6 @@ void FileOptions::MergeFrom(const FileOptions& from) {
set_has_csharp_namespace();
csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_);
}
- if (from.has_javanano_use_deprecated_package()) {
- set_javanano_use_deprecated_package(from.javanano_use_deprecated_package());
- }
}
_extensions_.MergeFrom(from._extensions_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -8627,12 +8742,14 @@ void FileOptions::MergeFrom(const FileOptions& from) {
}
void FileOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FileOptions::CopyFrom(const FileOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -8664,7 +8781,6 @@ void FileOptions::InternalSwap(FileOptions* other) {
std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
objc_class_prefix_.Swap(&other->objc_class_prefix_);
csharp_namespace_.Swap(&other->csharp_namespace_);
- std::swap(javanano_use_deprecated_package_, other->javanano_use_deprecated_package_);
uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
@@ -8723,6 +8839,7 @@ void FileOptions::clear_java_package() {
return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileOptions::release_java_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
clear_has_java_package();
return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -8776,6 +8893,7 @@ void FileOptions::clear_java_outer_classname() {
return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileOptions::release_java_outer_classname() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
clear_has_java_outer_classname();
return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -8926,6 +9044,7 @@ void FileOptions::clear_go_package() {
return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileOptions::release_go_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
clear_has_go_package();
return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -9099,6 +9218,7 @@ void FileOptions::clear_objc_class_prefix() {
return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileOptions::release_objc_class_prefix() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
clear_has_objc_class_prefix();
return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -9152,6 +9272,7 @@ void FileOptions::clear_csharp_namespace() {
return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* FileOptions::release_csharp_namespace() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
clear_has_csharp_namespace();
return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -9165,30 +9286,6 @@ void FileOptions::clear_csharp_namespace() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
}
-// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-bool FileOptions::has_javanano_use_deprecated_package() const {
- return (_has_bits_[0] & 0x00004000u) != 0;
-}
-void FileOptions::set_has_javanano_use_deprecated_package() {
- _has_bits_[0] |= 0x00004000u;
-}
-void FileOptions::clear_has_javanano_use_deprecated_package() {
- _has_bits_[0] &= ~0x00004000u;
-}
-void FileOptions::clear_javanano_use_deprecated_package() {
- javanano_use_deprecated_package_ = false;
- clear_has_javanano_use_deprecated_package();
-}
- bool FileOptions::javanano_use_deprecated_package() const {
- // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
- return javanano_use_deprecated_package_;
-}
- void FileOptions::set_javanano_use_deprecated_package(bool value) {
- set_has_javanano_use_deprecated_package();
- javanano_use_deprecated_package_ = value;
- // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
-}
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -9293,9 +9390,18 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const {
}
void MessageOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
_extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(MessageOptions, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<MessageOptions*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -9316,7 +9422,7 @@ void MessageOptions::Clear() {
bool MessageOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions)
for (;;) {
@@ -9510,6 +9616,7 @@ void MessageOptions::SerializeWithCachedSizes(
}
int MessageOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions)
int total_size = 0;
if (_has_bits_[0 / 32] & 15u) {
@@ -9556,18 +9663,22 @@ int MessageOptions::ByteSize() const {
}
void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const MessageOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MessageOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MessageOptions)
MergeFrom(*source);
}
}
void MessageOptions::MergeFrom(const MessageOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -9591,12 +9702,14 @@ void MessageOptions::MergeFrom(const MessageOptions& from) {
}
void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MessageOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void MessageOptions::CopyFrom(const MessageOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MessageOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -9886,9 +9999,18 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const {
}
void FieldOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
_extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(FieldOptions, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<FieldOptions*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -9912,7 +10034,7 @@ void FieldOptions::Clear() {
bool FieldOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions)
for (;;) {
@@ -10170,6 +10292,7 @@ void FieldOptions::SerializeWithCachedSizes(
}
int FieldOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions)
int total_size = 0;
if (_has_bits_[0 / 32] & 63u) {
@@ -10228,18 +10351,22 @@ int FieldOptions::ByteSize() const {
}
void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FieldOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldOptions)
MergeFrom(*source);
}
}
void FieldOptions::MergeFrom(const FieldOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -10269,12 +10396,14 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
}
void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FieldOptions::CopyFrom(const FieldOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -10562,9 +10691,18 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const {
}
void EnumOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
_extensions_.Clear();
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(EnumOptions, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<EnumOptions*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -10585,7 +10723,7 @@ void EnumOptions::Clear() {
bool EnumOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions)
for (;;) {
@@ -10729,6 +10867,7 @@ void EnumOptions::SerializeWithCachedSizes(
}
int EnumOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions)
int total_size = 0;
if (_has_bits_[0 / 32] & 3u) {
@@ -10765,18 +10904,22 @@ int EnumOptions::ByteSize() const {
}
void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const EnumOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumOptions)
MergeFrom(*source);
}
}
void EnumOptions::MergeFrom(const EnumOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -10794,12 +10937,14 @@ void EnumOptions::MergeFrom(const EnumOptions& from) {
}
void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void EnumOptions::CopyFrom(const EnumOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -10983,6 +11128,7 @@ EnumValueOptions* EnumValueOptions::New(::google::protobuf::Arena* arena) const
}
void EnumValueOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
_extensions_.Clear();
deprecated_ = false;
uninterpreted_option_.Clear();
@@ -10994,7 +11140,7 @@ void EnumValueOptions::Clear() {
bool EnumValueOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions)
for (;;) {
@@ -11113,6 +11259,7 @@ void EnumValueOptions::SerializeWithCachedSizes(
}
int EnumValueOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions)
int total_size = 0;
// optional bool deprecated = 1 [default = false];
@@ -11142,18 +11289,22 @@ int EnumValueOptions::ByteSize() const {
}
void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const EnumValueOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueOptions)
MergeFrom(*source);
}
}
void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -11168,12 +11319,14 @@ void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
}
void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void EnumValueOptions::CopyFrom(const EnumValueOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -11332,6 +11485,7 @@ ServiceOptions* ServiceOptions::New(::google::protobuf::Arena* arena) const {
}
void ServiceOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
_extensions_.Clear();
deprecated_ = false;
uninterpreted_option_.Clear();
@@ -11343,7 +11497,7 @@ void ServiceOptions::Clear() {
bool ServiceOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions)
for (;;) {
@@ -11462,6 +11616,7 @@ void ServiceOptions::SerializeWithCachedSizes(
}
int ServiceOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions)
int total_size = 0;
// optional bool deprecated = 33 [default = false];
@@ -11491,18 +11646,22 @@ int ServiceOptions::ByteSize() const {
}
void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const ServiceOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceOptions)
MergeFrom(*source);
}
}
void ServiceOptions::MergeFrom(const ServiceOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -11517,12 +11676,14 @@ void ServiceOptions::MergeFrom(const ServiceOptions& from) {
}
void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void ServiceOptions::CopyFrom(const ServiceOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -11681,6 +11842,7 @@ MethodOptions* MethodOptions::New(::google::protobuf::Arena* arena) const {
}
void MethodOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
_extensions_.Clear();
deprecated_ = false;
uninterpreted_option_.Clear();
@@ -11692,7 +11854,7 @@ void MethodOptions::Clear() {
bool MethodOptions::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions)
for (;;) {
@@ -11811,6 +11973,7 @@ void MethodOptions::SerializeWithCachedSizes(
}
int MethodOptions::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions)
int total_size = 0;
// optional bool deprecated = 33 [default = false];
@@ -11840,18 +12003,22 @@ int MethodOptions::ByteSize() const {
}
void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const MethodOptions* source =
::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodOptions)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodOptions)
MergeFrom(*source);
}
}
void MethodOptions::MergeFrom(const MethodOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
@@ -11866,12 +12033,14 @@ void MethodOptions::MergeFrom(const MethodOptions& from) {
}
void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void MethodOptions::CopyFrom(const MethodOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodOptions)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -12033,6 +12202,7 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protob
}
void UninterpretedOption_NamePart::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
if (_has_bits_[0 / 32] & 3u) {
if (has_name_part()) {
name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -12047,7 +12217,7 @@ void UninterpretedOption_NamePart::Clear() {
bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart)
for (;;) {
@@ -12161,6 +12331,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
}
int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
+// @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart)
int total_size = 0;
if (has_name_part()) {
@@ -12178,6 +12349,7 @@ int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
return total_size;
}
int UninterpretedOption_NamePart::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart)
int total_size = 0;
if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present.
@@ -12204,18 +12376,22 @@ int UninterpretedOption_NamePart::ByteSize() const {
}
void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const UninterpretedOption_NamePart* source =
::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption.NamePart)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption.NamePart)
MergeFrom(*source);
}
}
void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name_part()) {
@@ -12232,12 +12408,14 @@ void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart&
}
void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption.NamePart)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption.NamePart)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -12350,8 +12528,17 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena)
}
void UninterpretedOption::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(UninterpretedOption, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<UninterpretedOption*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -12383,7 +12570,7 @@ void UninterpretedOption::Clear() {
bool UninterpretedOption::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption)
for (;;) {
@@ -12641,6 +12828,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
}
int UninterpretedOption::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption)
int total_size = 0;
if (_has_bits_[1 / 32] & 126u) {
@@ -12705,18 +12893,22 @@ int UninterpretedOption::ByteSize() const {
}
void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const UninterpretedOption* source =
::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption)
MergeFrom(*source);
}
}
void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
name_.MergeFrom(from.name_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
@@ -12748,12 +12940,14 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
}
void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void UninterpretedOption::CopyFrom(const UninterpretedOption& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -12833,6 +13027,7 @@ void UninterpretedOption_NamePart::clear_name_part() {
return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* UninterpretedOption_NamePart::release_name_part() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
clear_has_name_part();
return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -12944,6 +13139,7 @@ void UninterpretedOption::clear_identifier_value() {
return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* UninterpretedOption::release_identifier_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
clear_has_identifier_value();
return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -13069,6 +13265,7 @@ void UninterpretedOption::clear_string_value() {
return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* UninterpretedOption::release_string_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
clear_has_string_value();
return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -13122,6 +13319,7 @@ void UninterpretedOption::clear_aggregate_value() {
return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* UninterpretedOption::release_aggregate_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
clear_has_aggregate_value();
return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -13210,6 +13408,7 @@ SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena*
}
void SourceCodeInfo_Location::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
if (_has_bits_[0 / 32] & 12u) {
if (has_leading_comments()) {
leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -13229,7 +13428,7 @@ void SourceCodeInfo_Location::Clear() {
bool SourceCodeInfo_Location::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location)
for (;;) {
@@ -13479,6 +13678,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
}
int SourceCodeInfo_Location::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location)
int total_size = 0;
if (_has_bits_[2 / 32] & 12u) {
@@ -13550,18 +13750,22 @@ int SourceCodeInfo_Location::ByteSize() const {
}
void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const SourceCodeInfo_Location* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo.Location)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo.Location)
MergeFrom(*source);
}
}
void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
path_.MergeFrom(from.path_);
span_.MergeFrom(from.span_);
@@ -13582,12 +13786,14 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
}
void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo.Location)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo.Location)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -13686,6 +13892,7 @@ SourceCodeInfo* SourceCodeInfo::New(::google::protobuf::Arena* arena) const {
}
void SourceCodeInfo::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
location_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
@@ -13695,7 +13902,7 @@ void SourceCodeInfo::Clear() {
bool SourceCodeInfo::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo)
for (;;) {
@@ -13776,6 +13983,7 @@ void SourceCodeInfo::SerializeWithCachedSizes(
}
int SourceCodeInfo::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo)
int total_size = 0;
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
@@ -13798,18 +14006,22 @@ int SourceCodeInfo::ByteSize() const {
}
void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const SourceCodeInfo* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo)
MergeFrom(*source);
}
}
void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
location_.MergeFrom(from.location_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -13818,12 +14030,14 @@ void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
}
void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -13956,6 +14170,7 @@ void SourceCodeInfo_Location::clear_leading_comments() {
return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* SourceCodeInfo_Location::release_leading_comments() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
clear_has_leading_comments();
return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -14009,6 +14224,7 @@ void SourceCodeInfo_Location::clear_trailing_comments() {
return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
clear_has_trailing_comments();
return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -14051,6 +14267,7 @@ void SourceCodeInfo_Location::clear_leading_detached_comments() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
}
::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
return leading_detached_comments_.Add();
}
void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
@@ -14184,8 +14401,17 @@ GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::New(::google::protob
}
void GeneratedCodeInfo_Annotation::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(GeneratedCodeInfo_Annotation, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<GeneratedCodeInfo_Annotation*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -14211,7 +14437,7 @@ void GeneratedCodeInfo_Annotation::Clear() {
bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo.Annotation)
for (;;) {
@@ -14392,6 +14618,7 @@ void GeneratedCodeInfo_Annotation::SerializeWithCachedSizes(
}
int GeneratedCodeInfo_Annotation::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation)
int total_size = 0;
if (_has_bits_[1 / 32] & 14u) {
@@ -14446,18 +14673,22 @@ int GeneratedCodeInfo_Annotation::ByteSize() const {
}
void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const GeneratedCodeInfo_Annotation* source =
::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo.Annotation)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo.Annotation)
MergeFrom(*source);
}
}
void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
path_.MergeFrom(from.path_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
@@ -14478,12 +14709,14 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation&
}
void GeneratedCodeInfo_Annotation::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -14581,6 +14814,7 @@ GeneratedCodeInfo* GeneratedCodeInfo::New(::google::protobuf::Arena* arena) cons
}
void GeneratedCodeInfo::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
annotation_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
@@ -14590,7 +14824,7 @@ void GeneratedCodeInfo::Clear() {
bool GeneratedCodeInfo::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo)
for (;;) {
@@ -14671,6 +14905,7 @@ void GeneratedCodeInfo::SerializeWithCachedSizes(
}
int GeneratedCodeInfo::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo)
int total_size = 0;
// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
@@ -14693,18 +14928,22 @@ int GeneratedCodeInfo::ByteSize() const {
}
void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const GeneratedCodeInfo* source =
::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo)
MergeFrom(*source);
}
}
void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
annotation_.MergeFrom(from.annotation_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -14713,12 +14952,14 @@ void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
}
void GeneratedCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -14821,6 +15062,7 @@ void GeneratedCodeInfo_Annotation::clear_source_file() {
return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+ // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
clear_has_source_file();
return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 3fe07bf5..92a0a3a7 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -993,24 +993,42 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
// nested types ----------------------------------------------------
typedef FieldDescriptorProto_Type Type;
- static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE;
- static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT;
- static const Type TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64;
- static const Type TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64;
- static const Type TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32;
- static const Type TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64;
- static const Type TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32;
- static const Type TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL;
- static const Type TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING;
- static const Type TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP;
- static const Type TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE;
- static const Type TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES;
- static const Type TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32;
- static const Type TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM;
- static const Type TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32;
- static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
- static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
- static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
+ static const Type TYPE_DOUBLE =
+ FieldDescriptorProto_Type_TYPE_DOUBLE;
+ static const Type TYPE_FLOAT =
+ FieldDescriptorProto_Type_TYPE_FLOAT;
+ static const Type TYPE_INT64 =
+ FieldDescriptorProto_Type_TYPE_INT64;
+ static const Type TYPE_UINT64 =
+ FieldDescriptorProto_Type_TYPE_UINT64;
+ static const Type TYPE_INT32 =
+ FieldDescriptorProto_Type_TYPE_INT32;
+ static const Type TYPE_FIXED64 =
+ FieldDescriptorProto_Type_TYPE_FIXED64;
+ static const Type TYPE_FIXED32 =
+ FieldDescriptorProto_Type_TYPE_FIXED32;
+ static const Type TYPE_BOOL =
+ FieldDescriptorProto_Type_TYPE_BOOL;
+ static const Type TYPE_STRING =
+ FieldDescriptorProto_Type_TYPE_STRING;
+ static const Type TYPE_GROUP =
+ FieldDescriptorProto_Type_TYPE_GROUP;
+ static const Type TYPE_MESSAGE =
+ FieldDescriptorProto_Type_TYPE_MESSAGE;
+ static const Type TYPE_BYTES =
+ FieldDescriptorProto_Type_TYPE_BYTES;
+ static const Type TYPE_UINT32 =
+ FieldDescriptorProto_Type_TYPE_UINT32;
+ static const Type TYPE_ENUM =
+ FieldDescriptorProto_Type_TYPE_ENUM;
+ static const Type TYPE_SFIXED32 =
+ FieldDescriptorProto_Type_TYPE_SFIXED32;
+ static const Type TYPE_SFIXED64 =
+ FieldDescriptorProto_Type_TYPE_SFIXED64;
+ static const Type TYPE_SINT32 =
+ FieldDescriptorProto_Type_TYPE_SINT32;
+ static const Type TYPE_SINT64 =
+ FieldDescriptorProto_Type_TYPE_SINT64;
static inline bool Type_IsValid(int value) {
return FieldDescriptorProto_Type_IsValid(value);
}
@@ -1033,9 +1051,12 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
}
typedef FieldDescriptorProto_Label Label;
- static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
- static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
- static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
+ static const Label LABEL_OPTIONAL =
+ FieldDescriptorProto_Label_LABEL_OPTIONAL;
+ static const Label LABEL_REQUIRED =
+ FieldDescriptorProto_Label_LABEL_REQUIRED;
+ static const Label LABEL_REPEATED =
+ FieldDescriptorProto_Label_LABEL_REPEATED;
static inline bool Label_IsValid(int value) {
return FieldDescriptorProto_Label_IsValid(value);
}
@@ -1868,9 +1889,12 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef FileOptions_OptimizeMode OptimizeMode;
- static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
- static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
- static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME;
+ static const OptimizeMode SPEED =
+ FileOptions_OptimizeMode_SPEED;
+ static const OptimizeMode CODE_SIZE =
+ FileOptions_OptimizeMode_CODE_SIZE;
+ static const OptimizeMode LITE_RUNTIME =
+ FileOptions_OptimizeMode_LITE_RUNTIME;
static inline bool OptimizeMode_IsValid(int value) {
return FileOptions_OptimizeMode_IsValid(value);
}
@@ -2017,13 +2041,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
::std::string* release_csharp_namespace();
void set_allocated_csharp_namespace(::std::string* csharp_namespace);
- // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
- bool has_javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
- void clear_javanano_use_deprecated_package() PROTOBUF_DEPRECATED;
- static const int kJavananoUseDeprecatedPackageFieldNumber = 38;
- bool javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
- void set_javanano_use_deprecated_package(bool value) PROTOBUF_DEPRECATED;
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
int uninterpreted_option_size() const;
void clear_uninterpreted_option();
@@ -2067,8 +2084,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline void clear_has_objc_class_prefix();
inline void set_has_csharp_namespace();
inline void clear_has_csharp_namespace();
- inline void set_has_javanano_use_deprecated_package();
- inline void clear_has_javanano_use_deprecated_package();
::google::protobuf::internal::ExtensionSet _extensions_;
@@ -2083,14 +2098,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
bool cc_generic_services_;
int optimize_for_;
::google::protobuf::internal::ArenaStringPtr go_package_;
+ ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
+ ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool java_generic_services_;
bool py_generic_services_;
bool deprecated_;
bool cc_enable_arenas_;
- bool javanano_use_deprecated_package_;
- ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
- ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -2298,9 +2312,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef FieldOptions_CType CType;
- static const CType STRING = FieldOptions_CType_STRING;
- static const CType CORD = FieldOptions_CType_CORD;
- static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
+ static const CType STRING =
+ FieldOptions_CType_STRING;
+ static const CType CORD =
+ FieldOptions_CType_CORD;
+ static const CType STRING_PIECE =
+ FieldOptions_CType_STRING_PIECE;
static inline bool CType_IsValid(int value) {
return FieldOptions_CType_IsValid(value);
}
@@ -2323,9 +2340,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
}
typedef FieldOptions_JSType JSType;
- static const JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL;
- static const JSType JS_STRING = FieldOptions_JSType_JS_STRING;
- static const JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER;
+ static const JSType JS_NORMAL =
+ FieldOptions_JSType_JS_NORMAL;
+ static const JSType JS_STRING =
+ FieldOptions_JSType_JS_STRING;
+ static const JSType JS_NUMBER =
+ FieldOptions_JSType_JS_NUMBER;
static inline bool JSType_IsValid(int value) {
return FieldOptions_JSType_IsValid(value);
}
@@ -3696,6 +3716,7 @@ inline ::std::string* FileDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3749,6 +3770,7 @@ inline ::std::string* FileDescriptorProto::mutable_package() {
return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileDescriptorProto::release_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
clear_has_package();
return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3791,6 +3813,7 @@ inline void FileDescriptorProto::set_dependency(int index, const char* value, si
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
}
inline ::std::string* FileDescriptorProto::add_dependency() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency)
return dependency_.Add();
}
inline void FileDescriptorProto::add_dependency(const ::std::string& value) {
@@ -4023,6 +4046,7 @@ inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
return options_;
}
inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options)
clear_has_options();
::google::protobuf::FileOptions* temp = options_;
options_ = NULL;
@@ -4066,6 +4090,7 @@ inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_c
return source_code_info_;
}
inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info)
clear_has_source_code_info();
::google::protobuf::SourceCodeInfo* temp = source_code_info_;
source_code_info_ = NULL;
@@ -4122,6 +4147,7 @@ inline ::std::string* FileDescriptorProto::mutable_syntax() {
return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileDescriptorProto::release_syntax() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
clear_has_syntax();
return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4283,6 +4309,7 @@ inline ::std::string* DescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* DescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4503,6 +4530,7 @@ inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
return options_;
}
inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options)
clear_has_options();
::google::protobuf::MessageOptions* temp = options_;
options_ = NULL;
@@ -4578,6 +4606,7 @@ inline void DescriptorProto::set_reserved_name(int index, const char* value, siz
// @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
}
inline ::std::string* DescriptorProto::add_reserved_name() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name)
return reserved_name_.Add();
}
inline void DescriptorProto::add_reserved_name(const ::std::string& value) {
@@ -4647,6 +4676,7 @@ inline ::std::string* FieldDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4774,6 +4804,7 @@ inline ::std::string* FieldDescriptorProto::mutable_type_name() {
return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_type_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
clear_has_type_name();
return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4827,6 +4858,7 @@ inline ::std::string* FieldDescriptorProto::mutable_extendee() {
return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_extendee() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
clear_has_extendee();
return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4880,6 +4912,7 @@ inline ::std::string* FieldDescriptorProto::mutable_default_value() {
return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_default_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
clear_has_default_value();
return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4957,6 +4990,7 @@ inline ::std::string* FieldDescriptorProto::mutable_json_name() {
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FieldDescriptorProto::release_json_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
clear_has_json_name();
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -4997,6 +5031,7 @@ inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options()
return options_;
}
inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options)
clear_has_options();
::google::protobuf::FieldOptions* temp = options_;
options_ = NULL;
@@ -5057,6 +5092,7 @@ inline ::std::string* OneofDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* OneofDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5114,6 +5150,7 @@ inline ::std::string* EnumDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* EnumDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5184,6 +5221,7 @@ inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
return options_;
}
inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options)
clear_has_options();
::google::protobuf::EnumOptions* temp = options_;
options_ = NULL;
@@ -5244,6 +5282,7 @@ inline ::std::string* EnumValueDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* EnumValueDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5308,6 +5347,7 @@ inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_o
return options_;
}
inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options)
clear_has_options();
::google::protobuf::EnumValueOptions* temp = options_;
options_ = NULL;
@@ -5368,6 +5408,7 @@ inline ::std::string* ServiceDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* ServiceDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5438,6 +5479,7 @@ inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_optio
return options_;
}
inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options)
clear_has_options();
::google::protobuf::ServiceOptions* temp = options_;
options_ = NULL;
@@ -5498,6 +5540,7 @@ inline ::std::string* MethodDescriptorProto::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* MethodDescriptorProto::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5551,6 +5594,7 @@ inline ::std::string* MethodDescriptorProto::mutable_input_type() {
return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* MethodDescriptorProto::release_input_type() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
clear_has_input_type();
return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5604,6 +5648,7 @@ inline ::std::string* MethodDescriptorProto::mutable_output_type() {
return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* MethodDescriptorProto::release_output_type() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
clear_has_output_type();
return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5644,6 +5689,7 @@ inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options
return options_;
}
inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+ // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options)
clear_has_options();
::google::protobuf::MethodOptions* temp = options_;
options_ = NULL;
@@ -5752,6 +5798,7 @@ inline ::std::string* FileOptions::mutable_java_package() {
return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileOptions::release_java_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
clear_has_java_package();
return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5805,6 +5852,7 @@ inline ::std::string* FileOptions::mutable_java_outer_classname() {
return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileOptions::release_java_outer_classname() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
clear_has_java_outer_classname();
return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -5955,6 +6003,7 @@ inline ::std::string* FileOptions::mutable_go_package() {
return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileOptions::release_go_package() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
clear_has_go_package();
return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6128,6 +6177,7 @@ inline ::std::string* FileOptions::mutable_objc_class_prefix() {
return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileOptions::release_objc_class_prefix() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
clear_has_objc_class_prefix();
return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6181,6 +6231,7 @@ inline ::std::string* FileOptions::mutable_csharp_namespace() {
return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* FileOptions::release_csharp_namespace() {
+ // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
clear_has_csharp_namespace();
return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6194,30 +6245,6 @@ inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_na
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace)
}
-// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-inline bool FileOptions::has_javanano_use_deprecated_package() const {
- return (_has_bits_[0] & 0x00004000u) != 0;
-}
-inline void FileOptions::set_has_javanano_use_deprecated_package() {
- _has_bits_[0] |= 0x00004000u;
-}
-inline void FileOptions::clear_has_javanano_use_deprecated_package() {
- _has_bits_[0] &= ~0x00004000u;
-}
-inline void FileOptions::clear_javanano_use_deprecated_package() {
- javanano_use_deprecated_package_ = false;
- clear_has_javanano_use_deprecated_package();
-}
-inline bool FileOptions::javanano_use_deprecated_package() const {
- // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
- return javanano_use_deprecated_package_;
-}
-inline void FileOptions::set_javanano_use_deprecated_package(bool value) {
- set_has_javanano_use_deprecated_package();
- javanano_use_deprecated_package_ = value;
- // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
-}
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -6858,6 +6885,7 @@ inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* UninterpretedOption_NamePart::release_name_part() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
clear_has_name_part();
return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -6969,6 +6997,7 @@ inline ::std::string* UninterpretedOption::mutable_identifier_value() {
return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* UninterpretedOption::release_identifier_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
clear_has_identifier_value();
return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7094,6 +7123,7 @@ inline ::std::string* UninterpretedOption::mutable_string_value() {
return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* UninterpretedOption::release_string_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
clear_has_string_value();
return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7147,6 +7177,7 @@ inline ::std::string* UninterpretedOption::mutable_aggregate_value() {
return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* UninterpretedOption::release_aggregate_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
clear_has_aggregate_value();
return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7264,6 +7295,7 @@ inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
clear_has_leading_comments();
return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7317,6 +7349,7 @@ inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
clear_has_trailing_comments();
return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -7359,6 +7392,7 @@ inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, co
// @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
}
inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
return leading_detached_comments_.Add();
}
inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
@@ -7492,6 +7526,7 @@ inline ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* GeneratedCodeInfo_Annotation::release_source_file() {
+ // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
clear_has_source_file();
return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 3e664d59..08b15554 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -377,15 +377,13 @@ message FileOptions {
// Namespace for generated classes; defaults to the package.
optional string csharp_namespace = 37;
- // Whether the nano proto compiler should generate in the deprecated non-nano
- // suffixed package.
- optional bool javanano_use_deprecated_package = 38 [deprecated = true];
-
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
+
+ reserved 38;
}
message MessageOptions {
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index be8e0b72..f937b9ea 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -54,6 +54,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -5739,18 +5740,6 @@ TEST_F(ValidationErrorTest, ValidateProto3Enum) {
"}");
}
-TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) {
- // Lite runtime is not supported in proto3.
- BuildFileWithErrors(
- "name: 'foo.proto' "
- "syntax: 'proto3' "
- "options { "
- " optimize_for: LITE_RUNTIME "
- "} ",
- "foo.proto: foo.proto: OTHER: Lite runtime is not supported "
- "in proto3.\n");
-}
-
TEST_F(ValidationErrorTest, ValidateProto3Group) {
BuildFileWithErrors(
"name: 'foo.proto' "
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index b325944e..e3639346 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -83,9 +83,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\036google/protobuf/duration.proto\022\017google"
".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
- "\n\005nanos\030\002 \001(\005BP\n\023com.google.protobufB\rDu"
- "rationProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf"
- ".WellKnownTypesb\006proto3", 183);
+ "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
+ "rationProtoP\001Z*github.com/golang/protobu"
+ "f/ptypes/duration\240\001\001\242\002\003GPB\252\002\036Google.Prot"
+ "obuf.WellKnownTypesb\006proto3", 227);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/duration.proto", &protobuf_RegisterTypes);
Duration::default_instance_ = new Duration();
@@ -178,8 +179,17 @@ Duration* Duration::New(::google::protobuf::Arena* arena) const {
}
void Duration::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(Duration, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<Duration*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -195,7 +205,7 @@ void Duration::Clear() {
bool Duration::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Duration)
for (;;) {
@@ -287,6 +297,7 @@ void Duration::SerializeWithCachedSizes(
}
int Duration::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
int total_size = 0;
// optional int64 seconds = 1;
@@ -310,18 +321,22 @@ int Duration::ByteSize() const {
}
void Duration::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Duration* source =
::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration)
MergeFrom(*source);
}
}
void Duration::MergeFrom(const Duration& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.seconds() != 0) {
set_seconds(from.seconds());
@@ -332,12 +347,14 @@ void Duration::MergeFrom(const Duration& from) {
}
void Duration::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Duration::CopyFrom(const Duration& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Duration)
if (&from == this) return;
Clear();
MergeFrom(from);
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 78bcc74b..96c1796d 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -33,6 +33,7 @@ syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/duration";
option java_package = "com.google.protobuf";
option java_outer_classname = "DurationProto";
option java_multiple_files = true;
@@ -80,6 +81,7 @@ option objc_class_prefix = "GPB";
// end.nanos -= 1000000000;
// }
//
+//
message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 8d689ac8..9e83bd29 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -267,6 +267,16 @@ class DynamicMessage : public Message {
Metadata GetMetadata() const;
+ // We actually allocate more memory than sizeof(*this) when this
+ // class's memory is allocated via the global operator new. Thus, we need to
+ // manually call the global operator delete. Calling the destructor is taken
+ // care of for us. This makes DynamicMessage compatible with -fsized-delete.
+ // It doesn't work for MSVC though.
+#ifndef _MSC_VER
+ static void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+#endif // !_MSC_VER
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -442,8 +452,10 @@ DynamicMessage::~DynamicMessage() {
case FieldOptions::STRING: {
const ::std::string* default_value =
&(reinterpret_cast<const ArenaStringPtr*>(
- type_info_->prototype->OffsetToPointer(
- type_info_->offsets[i]))->Get(NULL));
+ reinterpret_cast<uint8*>(
+ type_info_->default_oneof_instance)
+ + type_info_->offsets[i])
+ ->Get(NULL));
reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
default_value, NULL);
break;
@@ -704,7 +716,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
// Oneof fields do not use any space.
if (!type->field(i)->containing_oneof()) {
int field_size = FieldSpaceUsed(type->field(i));
- size = AlignTo(size, min(kSafeAlignment, field_size));
+ size = AlignTo(size, std::min(kSafeAlignment, field_size));
offsets[i] = size;
size += field_size;
}
@@ -748,7 +760,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = type->oneof_decl(i)->field(j);
int field_size = OneofFieldSpaceUsed(field);
- oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size));
+ oneof_size = AlignTo(oneof_size, std::min(kSafeAlignment, field_size));
offsets[field->index()] = oneof_size;
oneof_size += field_size;
}
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index f2eec782..dcf84263 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -80,9 +80,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\033google/protobuf/empty.proto\022\017google.pr"
- "otobuf\"\007\n\005EmptyBP\n\023com.google.protobufB\n"
- "EmptyProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Protob"
- "uf.WellKnownTypesb\006proto3", 145);
+ "otobuf\"\007\n\005EmptyBy\n\023com.google.protobufB\n"
+ "EmptyProtoP\001Z\'github.com/golang/protobuf"
+ "/ptypes/empty\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Proto"
+ "buf.WellKnownTypesb\006proto3", 186);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/empty.proto", &protobuf_RegisterTypes);
Empty::default_instance_ = new Empty();
@@ -185,11 +186,12 @@ Empty* Empty::New(::google::protobuf::Arena* arena) const {
}
void Empty::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
}
bool Empty::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Empty)
for (;;) {
@@ -227,6 +229,7 @@ void Empty::SerializeWithCachedSizes(
}
int Empty::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty)
int total_size = 0;
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@@ -236,28 +239,34 @@ int Empty::ByteSize() const {
}
void Empty::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Empty* source =
::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty)
MergeFrom(*source);
}
}
void Empty::MergeFrom(const Empty& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
}
void Empty::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Empty::CopyFrom(const Empty& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Empty)
if (&from == this) return;
Clear();
MergeFrom(from);
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
index b96daf28..37f4cd10 100644
--- a/src/google/protobuf/empty.proto
+++ b/src/google/protobuf/empty.proto
@@ -33,6 +33,7 @@ syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/empty";
option java_package = "com.google.protobuf";
option java_outer_classname = "EmptyProto";
option java_multiple_files = true;
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 01a6ce56..c49ebceb 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -175,12 +175,13 @@ FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const {
}
void FieldMask::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
paths_.Clear();
}
bool FieldMask::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FieldMask)
for (;;) {
@@ -262,6 +263,7 @@ void FieldMask::SerializeWithCachedSizes(
}
int FieldMask::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
int total_size = 0;
// repeated string paths = 1;
@@ -278,29 +280,35 @@ int FieldMask::ByteSize() const {
}
void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FieldMask* source =
::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask)
MergeFrom(*source);
}
}
void FieldMask::MergeFrom(const FieldMask& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
paths_.MergeFrom(from.paths_);
}
void FieldMask::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FieldMask::CopyFrom(const FieldMask& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldMask)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -361,6 +369,7 @@ void FieldMask::clear_paths() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
}
::std::string* FieldMask::add_paths() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
return paths_.Add();
}
void FieldMask::add_paths(const ::std::string& value) {
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index 7189fd79..f5e0b655 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -164,6 +164,7 @@ inline void FieldMask::set_paths(int index, const char* value, size_t size) {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
}
inline ::std::string* FieldMask::add_paths() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths)
return paths_.Add();
}
inline void FieldMask::add_paths(const ::std::string& value) {
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index 908c8a86..6af6dbe8 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -88,7 +88,7 @@ option java_generate_equals_and_hash = true;
// operation applies to all fields (as if a FieldMask of all fields
// had been specified).
//
-// Note that a field mask does not necessarily applies to the
+// Note that a field mask does not necessarily apply to the
// top-level response message. In case of a REST get operation, the
// field mask applies directly to the response, but in case of a REST
// list operation, the mask instead applies to each individual message
@@ -162,6 +162,32 @@ option java_generate_equals_and_hash = true;
// mask: "user.displayName,photo"
// }
//
+// # Field Masks and Oneof Fields
+//
+// Field masks treat fields in oneofs just as regular fields. Consider the
+// following message:
+//
+// message SampleMessage {
+// oneof test_oneof {
+// string name = 4;
+// SubMessage sub_message = 9;
+// }
+// }
+//
+// The field mask can be:
+//
+// mask {
+// paths: "name"
+// }
+//
+// Or:
+//
+// mask {
+// paths: "sub_message"
+// }
+//
+// Note that oneof type names ("test_oneof" in this case) cannot be used in
+// paths.
message FieldMask {
// The set of field mask paths.
repeated string paths = 1;
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index eee024ee..2313181c 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -412,6 +412,15 @@ void GeneratedMessageReflection::SwapField(
#undef SWAP_ARRAYS
case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+ Swap<GenericTypeHandler<string> >(
+ MutableRaw<RepeatedPtrFieldBase>(message2, field));
+ break;
+ }
+ break;
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
MutableRaw<MapFieldBase>(message1, field)->
@@ -447,16 +456,50 @@ void GeneratedMessageReflection::SwapField(
SWAP_VALUES(ENUM , int );
#undef SWAP_VALUES
case FieldDescriptor::CPPTYPE_MESSAGE:
- std::swap(*MutableRaw<Message*>(message1, field),
- *MutableRaw<Message*>(message2, field));
+ if (GetArena(message1) == GetArena(message2)) {
+ std::swap(*MutableRaw<Message*>(message1, field),
+ *MutableRaw<Message*>(message2, field));
+ } else {
+ Message** sub_msg1 = MutableRaw<Message*>(message1, field);
+ Message** sub_msg2 = MutableRaw<Message*>(message2, field);
+ if (*sub_msg1 == NULL && *sub_msg2 == NULL) break;
+ if (*sub_msg1 && *sub_msg2) {
+ (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2);
+ break;
+ }
+ if (*sub_msg1 == NULL) {
+ *sub_msg1 = (*sub_msg2)->New(message1->GetArena());
+ (*sub_msg1)->CopyFrom(**sub_msg2);
+ ClearField(message2, field);
+ } else {
+ *sub_msg2 = (*sub_msg1)->New(message2->GetArena());
+ (*sub_msg2)->CopyFrom(**sub_msg1);
+ ClearField(message1, field);
+ }
+ }
break;
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
- MutableRaw<ArenaStringPtr>(message1, field)->Swap(
- MutableRaw<ArenaStringPtr>(message2, field));
+ {
+ Arena* arena1 = GetArena(message1);
+ Arena* arena2 = GetArena(message2);
+ ArenaStringPtr* string1 =
+ MutableRaw<ArenaStringPtr>(message1, field);
+ ArenaStringPtr* string2 =
+ MutableRaw<ArenaStringPtr>(message2, field);
+ if (arena1 == arena2) {
+ string1->Swap(string2);
+ } else {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ const string temp = string1->Get(default_ptr);
+ string1->Set(default_ptr, string2->Get(default_ptr), arena1);
+ string2->Set(default_ptr, temp, arena2);
+ }
+ }
break;
}
break;
@@ -1752,7 +1795,8 @@ bool GeneratedMessageReflection::InsertOrLookupMapValue(
"InsertOrLookupMapValue",
"Field is not a map field.");
val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
- return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val);
+ return MutableRaw<MapFieldBase>(message, field)->InsertOrLookupMapValue(
+ key, val);
}
bool GeneratedMessageReflection::DeleteMapValue(
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 9ef78710..15fc802c 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -582,7 +582,16 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
// which the offsets of the direct fields of a class are non-constant.
// Fields inherited from superclasses *can* have non-constant offsets,
// but that's not what this macro will be used for.
-//
+#if defined(__clang__)
+// For Clang we use __builtin_offsetof() and suppress the warning,
+// to avoid Control Flow Integrity and UBSan vptr sanitizers from
+// crashing while trying to validate the invalid reinterpet_casts.
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(TYPE, FIELD) \
+ _Pragma("clang diagnostic pop")
+#else
// Note that we calculate relative to the pointer value 16 here since if we
// just use zero, GCC complains about dereferencing a NULL pointer. We
// choose 16 rather than some other number just in case the compiler would
@@ -592,6 +601,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
reinterpret_cast<const char*>( \
&reinterpret_cast<const TYPE*>(16)->FIELD) - \
reinterpret_cast<const char*>(16))
+#endif
#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \
static_cast<int>( \
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 78c8d7ff..4475556a 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -42,8 +42,8 @@
#include <string>
#include <google/protobuf/stubs/once.h>
-
#include <google/protobuf/stubs/common.h>
+
namespace google {
namespace protobuf {
@@ -63,6 +63,8 @@ namespace internal {
#undef DEPRECATED_PROTOBUF_FIELD
#define PROTOBUF_DEPRECATED
+#define PROTOBUF_DEPRECATED_ATTR
+
// Constants for special floating point values.
LIBPROTOBUF_EXPORT double Infinity();
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index e3a34d0a..d8354c1f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -105,7 +105,7 @@ void CodedInputStream::BackUpInputToCurrentPosition() {
inline void CodedInputStream::RecomputeBufferLimits() {
buffer_end_ += buffer_size_after_limit_;
- int closest_limit = min(current_limit_, total_bytes_limit_);
+ int closest_limit = std::min(current_limit_, total_bytes_limit_);
if (closest_limit < total_bytes_read_) {
// The limit position is in the current buffer. We must adjust
// the buffer size accordingly.
@@ -135,7 +135,7 @@ CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
// We need to enforce all limits, not just the new one, so if the previous
// limit was before the new requested limit, we continue to enforce the
// previous limit.
- current_limit_ = min(current_limit_, old_limit);
+ current_limit_ = std::min(current_limit_, old_limit);
RecomputeBufferLimits();
return old_limit;
@@ -188,7 +188,7 @@ void CodedInputStream::SetTotalBytesLimit(
// Make sure the limit isn't already past, since this could confuse other
// code.
int current_position = CurrentPosition();
- total_bytes_limit_ = max(current_position, total_bytes_limit);
+ total_bytes_limit_ = std::max(current_position, total_bytes_limit);
if (warning_threshold >= 0) {
total_bytes_warning_threshold_ = warning_threshold;
} else {
@@ -233,7 +233,7 @@ bool CodedInputStream::Skip(int count) {
buffer_end_ = buffer_;
// Make sure this skip doesn't try to skip past the current limit.
- int closest_limit = min(current_limit_, total_bytes_limit_);
+ int closest_limit = std::min(current_limit_, total_bytes_limit_);
int bytes_until_limit = closest_limit - total_bytes_read_;
if (bytes_until_limit < count) {
// We hit the limit. Skip up to it then fail.
@@ -270,7 +270,7 @@ bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
buffer->clear();
}
- int closest_limit = min(current_limit_, total_bytes_limit_);
+ int closest_limit = std::min(current_limit_, total_bytes_limit_);
if (closest_limit != INT_MAX) {
int bytes_to_limit = closest_limit - CurrentPosition();
if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index e3771003..c81a33ac 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -1136,7 +1136,7 @@ inline void CodedOutputStream::WriteVarint32(uint32 value) {
// this write won't cross the end, so we can skip the checks.
uint8* target = buffer_;
uint8* end = WriteVarint32ToArray(value, target);
- int size = end - target;
+ int size = static_cast<int>(end - target);
Advance(size);
} else {
WriteVarint32SlowPath(value);
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index d1782e39..a8108e45 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -46,7 +46,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/scoped_ptr.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index 82445000..15b02fe3 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -43,10 +43,9 @@
#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
-#include <zlib.h>
-
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <zlib.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 7d886506..7532b098 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -42,13 +42,25 @@ namespace protobuf {
namespace io {
Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
- : variable_delimiter_(variable_delimiter),
- output_(output),
- buffer_(NULL),
- buffer_size_(0),
- at_start_of_line_(true),
- failed_(false) {
-}
+ : variable_delimiter_(variable_delimiter),
+ output_(output),
+ buffer_(NULL),
+ buffer_size_(0),
+ offset_(0),
+ at_start_of_line_(true),
+ failed_(false),
+ annotation_collector_(NULL) {}
+
+Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+ AnnotationCollector* annotation_collector)
+ : variable_delimiter_(variable_delimiter),
+ output_(output),
+ buffer_(NULL),
+ buffer_size_(0),
+ offset_(0),
+ at_start_of_line_(true),
+ failed_(false),
+ annotation_collector_(annotation_collector) {}
Printer::~Printer() {
// Only BackUp() if we have called Next() at least once and never failed.
@@ -57,9 +69,47 @@ Printer::~Printer() {
}
}
+bool Printer::GetSubstitutionRange(const char* varname,
+ pair<size_t, size_t>* range) {
+ map<string, pair<size_t, size_t> >::const_iterator iter =
+ substitutions_.find(varname);
+ if (iter == substitutions_.end()) {
+ GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
+ return false;
+ }
+ if (iter->second.first > iter->second.second) {
+ GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
+ << varname;
+ return false;
+ }
+ *range = iter->second;
+ return true;
+}
+
+void Printer::Annotate(const char* begin_varname, const char* end_varname,
+ const string& file_path, const vector<int>& path) {
+ if (annotation_collector_ == NULL) {
+ // Can't generate signatures with this Printer.
+ return;
+ }
+ pair<size_t, size_t> begin, end;
+ if (!GetSubstitutionRange(begin_varname, &begin) ||
+ !GetSubstitutionRange(end_varname, &end)) {
+ return;
+ }
+ if (begin.first > end.second) {
+ GOOGLE_LOG(DFATAL) << " Annotation has negative length from " << begin_varname
+ << " to " << end_varname;
+ } else {
+ annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
+ path);
+ }
+}
+
void Printer::Print(const map<string, string>& variables, const char* text) {
int size = strlen(text);
int pos = 0; // The number of bytes we've written so far.
+ substitutions_.clear();
for (int i = 0; i < size; i++) {
if (text[i] == '\n') {
@@ -97,7 +147,17 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
if (iter == variables.end()) {
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
} else {
+ size_t begin = offset_;
WriteRaw(iter->second.data(), iter->second.size());
+ pair<map<string, pair<size_t, size_t> >::iterator, bool> inserted =
+ substitutions_.insert(
+ std::make_pair(varname, std::make_pair(begin, offset_)));
+ if (!inserted.second) {
+ // This variable was used multiple times. Make its span have
+ // negative length so we can detect it if it gets used in an
+ // annotation.
+ inserted.first->second = std::make_pair(1, 0);
+ }
}
}
@@ -265,6 +325,7 @@ void Printer::WriteRaw(const char* data, int size) {
// Data exceeds space in the buffer. Copy what we can and request a
// new buffer.
memcpy(buffer_, data, buffer_size_);
+ offset_ += buffer_size_;
data += buffer_size_;
size -= buffer_size_;
void* void_buffer;
@@ -277,6 +338,7 @@ void Printer::WriteRaw(const char* data, int size) {
memcpy(buffer_, data, size);
buffer_ += size;
buffer_size_ -= size;
+ offset_ += size;
}
} // namespace io
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index f1490bbe..2ba84559 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -39,6 +39,7 @@
#include <string>
#include <map>
+#include <vector>
#include <google/protobuf/stubs/common.h>
namespace google {
@@ -47,6 +48,47 @@ namespace io {
class ZeroCopyOutputStream; // zero_copy_stream.h
+// Records annotations about a Printer's output.
+class LIBPROTOBUF_EXPORT AnnotationCollector {
+ public:
+ // Records that the bytes in file_path beginning with begin_offset and ending
+ // before end_offset are associated with the SourceCodeInfo-style path.
+ virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+ const string& file_path,
+ const vector<int>& path) = 0;
+
+ virtual ~AnnotationCollector() {}
+};
+
+// Records annotations about a Printer's output to the given protocol buffer,
+// assuming that the buffer has an ::Annotation message exposing path,
+// source_file, begin and end fields.
+template <typename AnnotationProto>
+class AnnotationProtoCollector : public AnnotationCollector {
+ public:
+ // annotation_proto is the protocol buffer to which new Annotations should be
+ // added. It is not owned by the AnnotationProtoCollector.
+ explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
+ : annotation_proto_(annotation_proto) {}
+
+ // Override for AnnotationCollector::AddAnnotation.
+ virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
+ const string& file_path, const vector<int>& path) {
+ typename AnnotationProto::Annotation* annotation =
+ annotation_proto_->add_annotation();
+ for (int i = 0; i < path.size(); ++i) {
+ annotation->add_path(path[i]);
+ }
+ annotation->set_source_file(file_path);
+ annotation->set_begin(begin_offset);
+ annotation->set_end(end_offset);
+ }
+
+ private:
+ // The protocol buffer to which new annotations should be added.
+ AnnotationProto* const annotation_proto_;
+};
+
// This simple utility class assists in code generation. It basically
// allows the caller to define a set of variables and then output some
// text with variable substitutions. Example usage:
@@ -61,13 +103,103 @@ class ZeroCopyOutputStream; // zero_copy_stream.h
// Printer aggressively enforces correct usage, crashing (with assert failures)
// in the case of undefined variables in debug builds. This helps greatly in
// debugging code which uses it.
+//
+// If a Printer is constructed with an AnnotationCollector, it will provide it
+// with annotations that connect the Printer's output to paths that can identify
+// various descriptors. In the above example, if person_ is a descriptor that
+// identifies Bob, we can associate the output string "My name is Bob." with
+// a source path pointing to that descriptor with:
+//
+// printer.Annotate("name", person_);
+//
+// The AnnotationCollector will be sent an annotation linking the output range
+// covering "Bob" to the logical path provided by person_. Tools may use
+// this association to (for example) link "Bob" in the output back to the
+// source file that defined the person_ descriptor identifying Bob.
+//
+// Annotate can only examine variables substituted during the last call to
+// Print. It is invalid to refer to a variable that was used multiple times
+// in a single Print call.
+//
+// In full generality, one may specify a range of output text using a beginning
+// substitution variable and an ending variable. The resulting annotation will
+// span from the first character of the substituted value for the beginning
+// variable to the last character of the substituted value for the ending
+// variable. For example, the Annotate call above is equivalent to this one:
+//
+// printer.Annotate("name", "name", person_);
+//
+// This is useful if multiple variables combine to form a single span of output
+// that should be annotated with the same source path. For example:
+//
+// Printer printer(output, '$');
+// map<string, string> vars;
+// vars["first"] = "Alice";
+// vars["last"] = "Smith";
+// printer.Print(vars, "My name is $first$ $last$.");
+// printer.Annotate("first", "last", person_);
+//
+// This code would associate the span covering "Alice Smith" in the output with
+// the person_ descriptor.
+//
+// Note that the beginning variable must come before (or overlap with, in the
+// case of zero-sized substitution values) the ending variable.
+//
+// It is also sometimes useful to use variables with zero-sized values as
+// markers. This avoids issues with multiple references to the same variable
+// and also allows annotation ranges to span literal text from the Print
+// templates:
+//
+// Printer printer(output, '$');
+// map<string, string> vars;
+// vars["foo"] = "bar";
+// vars["function"] = "call";
+// vars["mark"] = "";
+// printer.Print(vars, "$function$($foo$,$foo$)$mark$");
+// printer.Annotate("function", "rmark", call_);
+//
+// This code associates the span covering "call(bar,bar)" in the output with the
+// call_ descriptor.
+
class LIBPROTOBUF_EXPORT Printer {
public:
// Create a printer that writes text to the given output stream. Use the
// given character as the delimiter for variables.
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
+
+ // Create a printer that writes text to the given output stream. Use the
+ // given character as the delimiter for variables. If annotation_collector
+ // is not null, Printer will provide it with annotations about code written
+ // to the stream. annotation_collector is not owned by Printer.
+ Printer(ZeroCopyOutputStream* output, char variable_delimiter,
+ AnnotationCollector* annotation_collector);
+
~Printer();
+ // Link a subsitution variable emitted by the last call to Print to the object
+ // described by descriptor.
+ template <typename SomeDescriptor>
+ void Annotate(const char* varname, const SomeDescriptor* descriptor) {
+ Annotate(varname, varname, descriptor);
+ }
+
+ // Link the output range defined by the substitution variables as emitted by
+ // the last call to Print to the object described by descriptor. The range
+ // begins at begin_varname's value and ends after the last character of the
+ // value substituted for end_varname.
+ template <typename SomeDescriptor>
+ void Annotate(const char* begin_varname, const char* end_varname,
+ const SomeDescriptor* descriptor) {
+ if (annotation_collector_ == NULL) {
+ // Annotations aren't turned on for this Printer, so don't pay the cost
+ // of building the location path.
+ return;
+ }
+ vector<int> path;
+ descriptor->GetLocationPath(&path);
+ Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
+ }
+
// Print some text after applying variable substitutions. If a particular
// variable in the text is not defined, this will crash. Variables to be
// substituted are identified by their names surrounded by delimiter
@@ -149,16 +281,48 @@ class LIBPROTOBUF_EXPORT Printer {
bool failed() const { return failed_; }
private:
+ // Link the output range defined by the substitution variables as emitted by
+ // the last call to Print to the object found at the SourceCodeInfo-style path
+ // in a file with path file_path. The range begins at the start of
+ // begin_varname's value and ends after the last character of the value
+ // substituted for end_varname. Note that begin_varname and end_varname
+ // may refer to the same variable.
+ void Annotate(const char* begin_varname, const char* end_varname,
+ const string& file_path, const vector<int>& path);
+
const char variable_delimiter_;
ZeroCopyOutputStream* const output_;
char* buffer_;
int buffer_size_;
+ // The current position, in bytes, in the output stream. This is equivalent
+ // to the total number of bytes that have been written so far. This value is
+ // used to calculate annotation ranges in the substitutions_ map below.
+ size_t offset_;
string indent_;
bool at_start_of_line_;
bool failed_;
+ // A map from variable name to [start, end) offsets in the output buffer.
+ // These refer to the offsets used for a variable after the last call to
+ // Print. If a variable was used more than once, the entry used in
+ // this map is set to a negative-length span. For singly-used variables, the
+ // start offset is the beginning of the substitution; the end offset is the
+ // last byte of the substitution plus one (such that (end - start) is the
+ // length of the substituted string).
+ map<string, pair<size_t, size_t> > substitutions_;
+
+ // Returns true and sets range to the substitution range in the output for
+ // varname if varname was used once in the last call to Print. If varname
+ // was not used, or if it was used multiple times, returns false (and
+ // fails a debug assertion).
+ bool GetSubstitutionRange(const char* varname, pair<size_t, size_t>* range);
+
+ // If non-null, annotation_collector_ is used to store annotations about
+ // generated code.
+ AnnotationCollector* const annotation_collector_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
};
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 258dd986..95f3afa2 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@@ -169,6 +170,196 @@ TEST(Printer, InlineVariableSubstitution) {
buffer);
}
+// MockDescriptorFile defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptorFile {
+ public:
+ explicit MockDescriptorFile(const string& file) : file_(file) {}
+
+ // The mock filename for this file.
+ const string& name() const { return file_; }
+
+ private:
+ string file_;
+};
+
+// MockDescriptor defines only those members that Printer uses to write out
+// annotations.
+class MockDescriptor {
+ public:
+ MockDescriptor(const string& file, const vector<int>& path)
+ : file_(file), path_(path) {}
+
+ // The mock file in which this descriptor was defined.
+ const MockDescriptorFile* file() const { return &file_; }
+
+ private:
+ // Allows access to GetLocationPath.
+ friend class ::google::protobuf::io::Printer;
+
+ // Copies the pre-stored path to output.
+ void GetLocationPath(std::vector<int>* output) const { *output = path_; }
+
+ MockDescriptorFile file_;
+ vector<int> path_;
+};
+
+TEST(Printer, AnnotateMap) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ map<string, string> vars;
+ vars["foo"] = "3";
+ vars["bar"] = "5";
+ printer.Print(vars, "012$foo$4$bar$\n");
+ vector<int> path_1;
+ path_1.push_back(33);
+ vector<int> path_2;
+ path_2.push_back(11);
+ path_2.push_back(22);
+ MockDescriptor descriptor_1("path_1", path_1);
+ MockDescriptor descriptor_2("path_2", path_2);
+ printer.Annotate("foo", "foo", &descriptor_1);
+ printer.Annotate("bar", "bar", &descriptor_2);
+ }
+ buffer[output.ByteCount()] = '\0';
+ EXPECT_STREQ("012345\n", buffer);
+ ASSERT_EQ(2, info.annotation_size());
+ const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+ ? &info.annotation(0)
+ : &info.annotation(1);
+ const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+ ? &info.annotation(1)
+ : &info.annotation(0);
+ ASSERT_EQ(1, foo->path_size());
+ ASSERT_EQ(2, bar->path_size());
+ EXPECT_EQ(33, foo->path(0));
+ EXPECT_EQ(11, bar->path(0));
+ EXPECT_EQ(22, bar->path(1));
+ EXPECT_EQ("path_1", foo->source_file());
+ EXPECT_EQ("path_2", bar->source_file());
+ EXPECT_EQ(3, foo->begin());
+ EXPECT_EQ(4, foo->end());
+ EXPECT_EQ(5, bar->begin());
+ EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateInline) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+ vector<int> path_1;
+ path_1.push_back(33);
+ vector<int> path_2;
+ path_2.push_back(11);
+ path_2.push_back(22);
+ MockDescriptor descriptor_1("path_1", path_1);
+ MockDescriptor descriptor_2("path_2", path_2);
+ printer.Annotate("foo", "foo", &descriptor_1);
+ printer.Annotate("bar", "bar", &descriptor_2);
+ }
+ buffer[output.ByteCount()] = '\0';
+ EXPECT_STREQ("012345\n", buffer);
+ ASSERT_EQ(2, info.annotation_size());
+ const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
+ ? &info.annotation(0)
+ : &info.annotation(1);
+ const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
+ ? &info.annotation(1)
+ : &info.annotation(0);
+ ASSERT_EQ(1, foo->path_size());
+ ASSERT_EQ(2, bar->path_size());
+ EXPECT_EQ(33, foo->path(0));
+ EXPECT_EQ(11, bar->path(0));
+ EXPECT_EQ(22, bar->path(1));
+ EXPECT_EQ("path_1", foo->source_file());
+ EXPECT_EQ("path_2", bar->source_file());
+ EXPECT_EQ(3, foo->begin());
+ EXPECT_EQ(4, foo->end());
+ EXPECT_EQ(5, bar->begin());
+ EXPECT_EQ(6, bar->end());
+}
+
+TEST(Printer, AnnotateRange) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ printer.Annotate("foo", "bar", &descriptor);
+ }
+ buffer[output.ByteCount()] = '\0';
+ EXPECT_STREQ("012345\n", buffer);
+ ASSERT_EQ(1, info.annotation_size());
+ const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0);
+ ASSERT_EQ(1, foobar->path_size());
+ EXPECT_EQ(33, foobar->path(0));
+ EXPECT_EQ("path", foobar->source_file());
+ EXPECT_EQ(3, foobar->begin());
+ EXPECT_EQ(6, foobar->end());
+}
+
+TEST(Printer, AnnotateEmptyRange) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
+ "", "bam", "");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ printer.Annotate("baz", "bam", &descriptor);
+ }
+ buffer[output.ByteCount()] = '\0';
+ EXPECT_STREQ("012345\n", buffer);
+ ASSERT_EQ(1, info.annotation_size());
+ const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0);
+ ASSERT_EQ(1, bazbam->path_size());
+ EXPECT_EQ(33, bazbam->path(0));
+ EXPECT_EQ("path", bazbam->source_file());
+ EXPECT_EQ(5, bazbam->begin());
+ EXPECT_EQ(5, bazbam->end());
+}
+
+TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ printer.Annotate("bar", "bar", &descriptor);
+ }
+ buffer[output.ByteCount()] = '\0';
+ EXPECT_STREQ("0123435\n", buffer);
+ ASSERT_EQ(1, info.annotation_size());
+ const GeneratedCodeInfo::Annotation* bar = &info.annotation(0);
+ ASSERT_EQ(1, bar->path_size());
+ EXPECT_EQ(33, bar->path(0));
+ EXPECT_EQ("path", bar->source_file());
+ EXPECT_EQ(6, bar->begin());
+ EXPECT_EQ(7, bar->end());
+}
+
TEST(Printer, Indenting) {
char buffer[8192];
@@ -232,6 +423,52 @@ TEST(Printer, Death) {
EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
}
+
+TEST(Printer, AnnotateMultipleUsesDeath) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$foo$\n", "foo", "3");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple");
+ }
+}
+
+TEST(Printer, AnnotateNegativeLengthDeath) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative");
+ }
+}
+
+TEST(Printer, AnnotateUndefinedDeath) {
+ char buffer[8192];
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ GeneratedCodeInfo info;
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+ {
+ Printer printer(&output, '$', &info_collector);
+ printer.Print("012$foo$4$foo$\n", "foo", "3");
+ vector<int> path;
+ path.push_back(33);
+ MockDescriptor descriptor("path", path);
+ EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor),
+ "Undefined");
+ }
+}
#endif // PROTOBUF_HAS_DEATH_TEST
TEST(Printer, WriteFailurePartial) {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 3d57707c..b3550dfb 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -881,9 +881,11 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
uint64 result = 0;
for (; *ptr != '\0'; ptr++) {
int digit = DigitValue(*ptr);
- GOOGLE_LOG_IF(DFATAL, digit < 0 || digit >= base)
- << " Tokenizer::ParseInteger() passed text that could not have been"
- " tokenized as an integer: " << CEscape(text);
+ if (digit < 0 || digit >= base) {
+ // The token provided by Tokenizer is invalid. i.e., 099 is an invalid
+ // token, but Tokenizer still think it's integer.
+ return false;
+ }
if (digit > max_value || result > (max_value - digit) / base) {
// Overflow.
return false;
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 49885eda..64ee7d84 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -52,6 +52,12 @@ class ZeroCopyInputStream; // zero_copy_stream.h
class ErrorCollector;
class Tokenizer;
+// By "column number", the proto compiler refers to a count of the number
+// of bytes before a given byte, except that a tab character advances to
+// the next multiple of 8 bytes. Note in particular that column numbers
+// are zero-based, while many user interfaces use one-based column numbers.
+typedef int ColumnNumber;
+
// Abstract interface for an object which collects the errors that occur
// during parsing. A typical implementation might simply print the errors
// to stdout.
@@ -63,13 +69,14 @@ class LIBPROTOBUF_EXPORT ErrorCollector {
// Indicates that there was an error in the input at the given line and
// column numbers. The numbers are zero-based, so you may want to add
// 1 to each before printing them.
- virtual void AddError(int line, int column, const string& message) = 0;
+ virtual void AddError(int line, ColumnNumber column,
+ const string& message) = 0;
// Indicates that there was a warning in the input at the given line and
// column numbers. The numbers are zero-based, so you may want to add
// 1 to each before printing them.
- virtual void AddWarning(int /* line */, int /* column */,
- const string& /* message */) { }
+ virtual void AddWarning(int line, ColumnNumber column,
+ const string& message) { }
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
@@ -124,8 +131,8 @@ class LIBPROTOBUF_EXPORT Tokenizer {
// "line" and "column" specify the position of the first character of
// the token within the input stream. They are zero-based.
int line;
- int column;
- int end_column;
+ ColumnNumber column;
+ ColumnNumber end_column;
};
// Get the current token. This is updated when Next() is called. Before
@@ -263,7 +270,7 @@ class LIBPROTOBUF_EXPORT Tokenizer {
// Line and column number of current_char_ within the whole input stream.
int line_;
- int column_;
+ ColumnNumber column_;
// String to which text should be appended as we advance through it.
// Call RecordTo(&str) to start recording and StopRecording() to stop.
@@ -280,6 +287,7 @@ class LIBPROTOBUF_EXPORT Tokenizer {
// Since we count columns we need to interpret tabs somehow. We'll take
// the standard 8-character definition for lack of any way to do better.
+ // This must match the documentation of ColumnNumber.
static const int kTabWidth = 8;
// -----------------------------------------------------------------
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index 20d50a2c..ae0811f8 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -736,19 +736,13 @@ TEST_F(TokenizerTest, ParseInteger) {
EXPECT_EQ(0, ParseInteger("0x"));
uint64 i;
-#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet
+
// Test invalid integers that will never be tokenized as integers.
- EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("zxy", kuint64max, &i),
- "passed text that could not have been tokenized as an integer");
- EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("1.2", kuint64max, &i),
- "passed text that could not have been tokenized as an integer");
- EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("08", kuint64max, &i),
- "passed text that could not have been tokenized as an integer");
- EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("0xg", kuint64max, &i),
- "passed text that could not have been tokenized as an integer");
- EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i),
- "passed text that could not have been tokenized as an integer");
-#endif // PROTOBUF_HAS_DEATH_TEST
+ EXPECT_FALSE(Tokenizer::ParseInteger("zxy", kuint64max, &i));
+ EXPECT_FALSE(Tokenizer::ParseInteger("1.2", kuint64max, &i));
+ EXPECT_FALSE(Tokenizer::ParseInteger("08", kuint64max, &i));
+ EXPECT_FALSE(Tokenizer::ParseInteger("0xg", kuint64max, &i));
+ EXPECT_FALSE(Tokenizer::ParseInteger("-1", kuint64max, &i));
// Test overflows.
EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i));
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 083beca4..e6ca88c2 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -69,7 +69,7 @@ ArrayInputStream::~ArrayInputStream() {
bool ArrayInputStream::Next(const void** data, int* size) {
if (position_ < size_) {
- last_returned_size_ = min(block_size_, size_ - position_);
+ last_returned_size_ = std::min(block_size_, size_ - position_);
*data = data_ + position_;
*size = last_returned_size_;
position_ += last_returned_size_;
@@ -122,7 +122,7 @@ ArrayOutputStream::~ArrayOutputStream() {
bool ArrayOutputStream::Next(void** data, int* size) {
if (position_ < size_) {
- last_returned_size_ = min(block_size_, size_ - position_);
+ last_returned_size_ = std::min(block_size_, size_ - position_);
*data = data_ + position_;
*size = last_returned_size_;
position_ += last_returned_size_;
@@ -157,7 +157,7 @@ StringOutputStream::~StringOutputStream() {
}
bool StringOutputStream::Next(void** data, int* size) {
- GOOGLE_CHECK_NE(NULL, target_);
+ GOOGLE_CHECK(target_ != NULL);
int old_size = target_->size();
// Grow the string.
@@ -177,9 +177,9 @@ bool StringOutputStream::Next(void** data, int* size) {
// Double the size, also make sure that the new size is at least
// kMinimumSize.
STLStringResizeUninitialized(
- target_,
- max(old_size * 2,
- kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
+ target_,
+ std::max(old_size * 2,
+ kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
}
*data = mutable_string_data(target_) + old_size;
@@ -189,13 +189,13 @@ bool StringOutputStream::Next(void** data, int* size) {
void StringOutputStream::BackUp(int count) {
GOOGLE_CHECK_GE(count, 0);
- GOOGLE_CHECK_NE(NULL, target_);
+ GOOGLE_CHECK(target_ != NULL);
GOOGLE_CHECK_LE(count, target_->size());
target_->resize(target_->size() - count);
}
int64 StringOutputStream::ByteCount() const {
- GOOGLE_CHECK_NE(NULL, target_);
+ GOOGLE_CHECK(target_ != NULL);
return target_->size();
}
@@ -235,8 +235,8 @@ int CopyingInputStream::Skip(int count) {
char junk[4096];
int skipped = 0;
while (skipped < count) {
- int bytes = Read(junk, min(count - skipped,
- implicit_cast<int>(sizeof(junk))));
+ int bytes =
+ Read(junk, std::min(count - skipped, implicit_cast<int>(sizeof(junk))));
if (bytes <= 0) {
// EOF or read error.
return skipped;
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 1c397dea..9d81ccfb 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -51,6 +51,7 @@
#include <string>
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -174,7 +175,7 @@ class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream {
int64 ByteCount() const;
private:
- const scoped_ptr<ResultCallback<string*> > callback_;
+ const google::protobuf::scoped_ptr<ResultCallback<string*> > callback_;
bool string_is_set_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyStringOutputStream);
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 8c7358c1..a9db8872 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -63,8 +63,9 @@
#endif
#include <sstream>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#if HAVE_ZLIB
#include <google/protobuf/io/gzip_stream.h>
@@ -72,7 +73,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <google/protobuf/testing/file.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index d1948ab5..3ca3fbaf 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -686,6 +686,33 @@ int main(int argc, char* argv[]) {
EXPECT_TRUE(map_message.IsInitialized());
}
+ {
+ // Check that adding more values to enum does not corrupt message
+ // when passed through an old client.
+ protobuf_unittest::V2MessageLite v2_message;
+ v2_message.set_int_field(800);
+ // Set enum field to the value not understood by the old client.
+ v2_message.set_enum_field(protobuf_unittest::V2_SECOND);
+ string v2_bytes = v2_message.SerializeAsString();
+
+ protobuf_unittest::V1MessageLite v1_message;
+ v1_message.ParseFromString(v2_bytes);
+ EXPECT_TRUE(v1_message.IsInitialized());
+ EXPECT_EQ(v1_message.int_field(), v2_message.int_field());
+ // V1 client does not understand V2_SECOND value, so it discards it and
+ // uses default value instead.
+ EXPECT_EQ(v1_message.enum_field(), protobuf_unittest::V1_FIRST);
+
+ // However, when re-serialized, it should preserve enum value.
+ string v1_bytes = v1_message.SerializeAsString();
+
+ protobuf_unittest::V2MessageLite same_v2_message;
+ same_v2_message.ParseFromString(v1_bytes);
+
+ EXPECT_EQ(v2_message.int_field(), same_v2_message.int_field());
+ EXPECT_EQ(v2_message.enum_field(), same_v2_message.enum_field());
+ }
+
std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 37e19b0a..bb0b14f9 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -31,9 +31,11 @@
#ifndef GOOGLE_PROTOBUF_MAP_H__
#define GOOGLE_PROTOBUF_MAP_H__
-#include <iterator>
#include <google/protobuf/stubs/hash.h>
+#include <iterator>
#include <limits> // To support Visual Studio 2008
+#include <set>
+#include <utility>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
@@ -41,17 +43,23 @@
#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
+#if __cpp_exceptions && LANG_CXX11
+#include <random>
+#endif
namespace google {
namespace protobuf {
+// The Map and MapIterator types are provided by this header file.
+// Please avoid using other types defined here, unless they are public
+// types within Map or MapIterator, such as Map::value_type.
template <typename Key, typename T>
class Map;
-template <typename Enum> struct is_proto_enum;
-
class MapIterator;
+template <typename Enum> struct is_proto_enum;
+
namespace internal {
template <typename Key, typename T,
WireFormatLite::FieldType key_wire_type,
@@ -73,15 +81,15 @@ class DynamicMapField;
class GeneratedMessageReflection;
} // namespace internal
-#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
- if (type() != EXPECTEDTYPE) { \
- GOOGLE_LOG(FATAL) \
- << "Protocol Buffer map usage error:\n" \
- << METHOD << " type does not match\n" \
- << " Expected : " \
- << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
- << " Actual : " \
- << FieldDescriptor::CppTypeName(type()); \
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
+ if (type() != EXPECTEDTYPE) { \
+ GOOGLE_LOG(FATAL) \
+ << "Protocol Buffer map usage error:\n" \
+ << METHOD << " type does not match\n" \
+ << " Expected : " \
+ << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
+ << " Actual : " \
+ << FieldDescriptor::CppTypeName(type()); \
}
// MapKey is an union type for representing any possible
@@ -166,11 +174,47 @@ class LIBPROTOBUF_EXPORT MapKey {
return *val_.string_value_;
}
+ bool operator<(const MapKey& other) const {
+ if (type_ != other.type_) {
+ // We could define a total order that handles this case, but
+ // there currently no need. So, for now, fail.
+ GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
+ }
+ switch (type()) {
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Unsupported";
+ return false;
+ case FieldDescriptor::CPPTYPE_STRING:
+ return *val_.string_value_ < *other.val_.string_value_;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return val_.int64_value_ < other.val_.int64_value_;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return val_.int32_value_ < other.val_.int32_value_;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return val_.uint64_value_ < other.val_.uint64_value_;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return val_.uint32_value_ < other.val_.uint32_value_;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return val_.bool_value_ < other.val_.bool_value_;
+ }
+ return false;
+ }
+
bool operator==(const MapKey& other) const {
if (type_ != other.type_) {
- return false;
+ // To be consistent with operator<, we don't allow this either.
+ GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
}
switch (type()) {
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Unsupported";
+ break;
case FieldDescriptor::CPPTYPE_STRING:
return *val_.string_value_ == *other.val_.string_value_;
case FieldDescriptor::CPPTYPE_INT64:
@@ -183,11 +227,6 @@ class LIBPROTOBUF_EXPORT MapKey {
return val_.uint32_value_ == other.val_.uint32_value_;
case FieldDescriptor::CPPTYPE_BOOL:
return val_.bool_value_ == other.val_.bool_value_;
- case FieldDescriptor::CPPTYPE_DOUBLE:
- case FieldDescriptor::CPPTYPE_FLOAT:
- case FieldDescriptor::CPPTYPE_ENUM:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- GOOGLE_LOG(FATAL) << "Can't get here.";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
@@ -196,6 +235,12 @@ class LIBPROTOBUF_EXPORT MapKey {
void CopyFrom(const MapKey& other) {
SetType(other.type());
switch (type_) {
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Unsupported";
+ break;
case FieldDescriptor::CPPTYPE_STRING:
*val_.string_value_ = *other.val_.string_value_;
break;
@@ -214,12 +259,6 @@ class LIBPROTOBUF_EXPORT MapKey {
case FieldDescriptor::CPPTYPE_BOOL:
val_.bool_value_ = other.val_.bool_value_;
break;
- case FieldDescriptor::CPPTYPE_DOUBLE:
- case FieldDescriptor::CPPTYPE_FLOAT:
- case FieldDescriptor::CPPTYPE_ENUM:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- GOOGLE_LOG(FATAL) << "Can't get here.";
- break;
}
}
@@ -457,8 +496,17 @@ class MapPair {
};
// google::protobuf::Map is an associative container type used to store protobuf map
-// fields. Its interface is similar to std::unordered_map. Users should use this
-// interface directly to visit or change map fields.
+// fields. Each Map instance may or may not use a different hash function, a
+// different iteration order, and so on. E.g., please don't examine
+// implementation details to decide if the following would work:
+// Map<int, int> m0, m1;
+// m0[0] = m1[0] = m0[1] = m1[1] = 0;
+// assert(m0.begin()->first == m1.begin()->first); // Bug!
+//
+// Map's interface is similar to std::unordered_map, except that Map is not
+// designed to play well with exceptions. Mutations to a Map do not invalidate
+// a Map's iterators, pointers to elements, or references to elements. Except
+// for erase(iterator), any non-const method can reorder iterators.
template <typename Key, typename T>
class Map {
public:
@@ -473,40 +521,56 @@ class Map {
typedef size_t size_type;
typedef hash<Key> hasher;
- typedef equal_to<Key> key_equal;
- Map()
+ Map(bool old_style = true)
: arena_(NULL),
- allocator_(arena_),
- elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(0) {}
- explicit Map(Arena* arena)
+ default_enum_value_(0),
+ old_style_(old_style) {
+ Init();
+ }
+ explicit Map(Arena* arena, bool old_style = true)
: arena_(arena),
- allocator_(arena_),
- elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(0) {
- arena_->OwnDestructor(&elements_);
+ default_enum_value_(0),
+ old_style_(old_style) {
+ Init();
}
-
Map(const Map& other)
: arena_(NULL),
- allocator_(arena_),
- elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(other.default_enum_value_) {
+ default_enum_value_(other.default_enum_value_),
+ old_style_(other.old_style_) {
+ Init();
insert(other.begin(), other.end());
}
template <class InputIt>
- Map(const InputIt& first, const InputIt& last)
+ Map(const InputIt& first, const InputIt& last, bool old_style = true)
: arena_(NULL),
- allocator_(arena_),
- elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(0) {
+ default_enum_value_(0),
+ old_style_(old_style) {
+ Init();
insert(first, last);
}
- ~Map() { clear(); }
+ ~Map() {
+ clear();
+ if (arena_ == NULL) {
+ if (old_style_)
+ delete deprecated_elements_;
+ else
+ delete elements_;
+ }
+ }
private:
+ void Init() {
+ if (old_style_)
+ deprecated_elements_ = Arena::Create<DeprecatedInnerMap>(
+ arena_, 0, hasher(), equal_to<Key>(),
+ MapAllocator<std::pair<const Key, MapPair<Key, T>*> >(arena_));
+ else
+ elements_ =
+ Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_));
+ }
+
// re-implement std::allocator to use arena allocator for memory allocation.
// Used for google::protobuf::Map implementation. Users should not use this class
// directly.
@@ -545,14 +609,17 @@ class Map {
}
#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
- !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
+ !defined(GOOGLE_PROTOBUF_OS_NACL) && \
+ !defined(GOOGLE_PROTOBUF_OS_ANDROID) && \
+ !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN)
template<class NodeType, class... Args>
void construct(NodeType* p, Args&&... args) {
- // Clang 3.6 doesn't compile static casting to void* directly. (Issue #1266)
- // According C++ standard 5.2.9/1: "The static_cast operator shall not cast
- // away constness". So first the maybe const pointer is casted to const void* and
- // after the const void* is const casted.
- new (const_cast<void*>(static_cast<const void*>(p))) NodeType(std::forward<Args>(args)...);
+ // Clang 3.6 doesn't compile static casting to void* directly. (Issue
+ // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall
+ // not cast away constness". So first the maybe const pointer is casted to
+ // const void* and after the const void* is const casted.
+ new (const_cast<void*>(static_cast<const void*>(p)))
+ NodeType(std::forward<Args>(args)...);
}
template<class NodeType>
@@ -593,86 +660,849 @@ class Map {
friend class MapAllocator;
};
- typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
- typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator>
- InnerMap;
+ // InnerMap's key type is Key and its value type is value_type*. We use a
+ // custom class here and for Node, below, to ensure that k_ is at offset 0,
+ // allowing safe conversion from pointer to Node to pointer to Key, and vice
+ // versa when appropriate.
+ class KeyValuePair {
+ public:
+ KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {}
+
+ const Key& key() const { return k_; }
+ Key& key() { return k_; }
+ value_type* const value() const { return v_; }
+ value_type*& value() { return v_; }
+
+ private:
+ Key k_;
+ value_type* v_;
+ };
+
+ typedef MapAllocator<KeyValuePair> Allocator;
+
+ // InnerMap is a generic hash-based map. It doesn't contain any
+ // protocol-buffer-specific logic. It is a chaining hash map with the
+ // additional feature that some buckets can be converted to use an ordered
+ // container. This ensures O(lg n) bounds on find, insert, and erase, while
+ // avoiding the overheads of ordered containers most of the time.
+ //
+ // The implementation doesn't need the full generality of unordered_map,
+ // and it doesn't have it. More bells and whistles can be added as needed.
+ // Some implementation details:
+ // 1. The hash function has type hasher and the equality function
+ // equal_to<Key>. We inherit from hasher to save space
+ // (empty-base-class optimization).
+ // 2. The number of buckets is a power of two.
+ // 3. Buckets are converted to trees in pairs: if we convert bucket b then
+ // buckets b and b^1 will share a tree. Invariant: buckets b and b^1 have
+ // the same non-NULL value iff they are sharing a tree. (An alternative
+ // implementation strategy would be to have a tag bit per bucket.)
+ // 4. As is typical for hash_map and such, the Keys and Values are always
+ // stored in linked list nodes. Pointers to elements are never invalidated
+ // until the element is deleted.
+ // 5. The trees' payload type is pointer to linked-list node. Tree-converting
+ // a bucket doesn't copy Key-Value pairs.
+ // 6. Once we've tree-converted a bucket, it is never converted back. However,
+ // the items a tree contains may wind up assigned to trees or lists upon a
+ // rehash.
+ // 7. The code requires no C++ features from C++11 or later.
+ // 8. Mutations to a map do not invalidate the map's iterators, pointers to
+ // elements, or references to elements.
+ // 9. Except for erase(iterator), any non-const method can reorder iterators.
+ class InnerMap : private hasher {
+ public:
+ typedef value_type* Value;
+
+ InnerMap(size_type n, hasher h, Allocator alloc)
+ : hasher(h),
+ num_elements_(0),
+ seed_(Seed()),
+ table_(NULL),
+ alloc_(alloc) {
+ n = TableSize(n);
+ table_ = CreateEmptyTable(n);
+ num_buckets_ = index_of_first_non_null_ = n;
+ }
+
+ ~InnerMap() {
+ if (table_ != NULL) {
+ clear();
+ Dealloc<void*>(table_, num_buckets_);
+ }
+ }
+
+ private:
+ enum { kMinTableSize = 8 };
+
+ // Linked-list nodes, as one would expect for a chaining hash table.
+ struct Node {
+ KeyValuePair kv;
+ Node* next;
+ };
+
+ // This is safe only if the given pointer is known to point to a Key that is
+ // part of a Node.
+ static Node* NodePtrFromKeyPtr(Key* k) {
+ return reinterpret_cast<Node*>(k);
+ }
+
+ static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
+
+ // Trees. The payload type is pointer to Key, so that we can query the tree
+ // with Keys that are not in any particular data structure. When we insert,
+ // though, the pointer is always pointing to a Key that is inside a Node.
+ struct KeyCompare {
+ bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
+ };
+ typedef typename Allocator::template rebind<Key*>::other KeyPtrAllocator;
+ typedef std::set<Key*, KeyCompare, KeyPtrAllocator> Tree;
+
+ // iterator and const_iterator are instantiations of iterator_base.
+ template <typename KeyValueType>
+ class iterator_base {
+ public:
+ typedef KeyValueType& reference;
+ typedef KeyValueType* pointer;
+ typedef typename Tree::iterator TreeIterator;
+
+ // Invariants:
+ // node_ is always correct. This is handy because the most common
+ // operations are operator* and operator-> and they only use node_.
+ // When node_ is set to a non-NULL value, all the other non-const fields
+ // are updated to be correct also, but those fields can become stale
+ // if the underlying map is modified. When those fields are needed they
+ // are rechecked, and updated if necessary.
+ iterator_base() : node_(NULL) {}
+
+ explicit iterator_base(const InnerMap* m) : m_(m) {
+ SearchFrom(m->index_of_first_non_null_);
+ }
+
+ // Any iterator_base can convert to any other. This is overkill, and we
+ // rely on the enclosing class to use it wisely. The standard "iterator
+ // can convert to const_iterator" is OK but the reverse direction is not.
+ template <typename U>
+ explicit iterator_base(const iterator_base<U>& it)
+ : node_(it.node_),
+ m_(it.m_),
+ bucket_index_(it.bucket_index_),
+ tree_it_(it.tree_it_) {}
+
+ iterator_base(Node* n, const InnerMap* m, size_type index)
+ : node_(n),
+ m_(m),
+ bucket_index_(index) {}
+
+ iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index)
+ : node_(NodePtrFromKeyPtr(*tree_it)),
+ m_(m),
+ bucket_index_(index),
+ tree_it_(tree_it) {
+ // Invariant: iterators that use tree_it_ have an even bucket_index_.
+ GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0);
+ }
+
+ // Advance through buckets, looking for the first that isn't empty.
+ // If nothing non-empty is found then leave node_ == NULL.
+ void SearchFrom(size_type start_bucket) {
+ GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
+ m_->table_[m_->index_of_first_non_null_] != NULL);
+ node_ = NULL;
+ for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_;
+ bucket_index_++) {
+ if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+ node_ = static_cast<Node*>(m_->table_[bucket_index_]);
+ break;
+ } else if (m_->TableEntryIsTree(bucket_index_)) {
+ Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+ GOOGLE_DCHECK(!tree->empty());
+ tree_it_ = tree->begin();
+ node_ = NodePtrFromKeyPtr(*tree_it_);
+ break;
+ }
+ }
+ }
+
+ reference operator*() const { return node_->kv; }
+ pointer operator->() const { return &(operator*()); }
+
+ friend bool operator==(const iterator_base& a, const iterator_base& b) {
+ return a.node_ == b.node_;
+ }
+ friend bool operator!=(const iterator_base& a, const iterator_base& b) {
+ return a.node_ != b.node_;
+ }
+
+ iterator_base& operator++() {
+ if (node_->next == NULL) {
+ const bool is_list = revalidate_if_necessary();
+ if (is_list) {
+ SearchFrom(bucket_index_ + 1);
+ } else {
+ GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0);
+ Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
+ if (++tree_it_ == tree->end()) {
+ SearchFrom(bucket_index_ + 2);
+ } else {
+ node_ = NodePtrFromKeyPtr(*tree_it_);
+ }
+ }
+ } else {
+ node_ = node_->next;
+ }
+ return *this;
+ }
+
+ iterator_base operator++(int /* unused */) {
+ iterator_base tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ // Assumes node_ and m_ are correct and non-NULL, but other fields may be
+ // stale. Fix them as needed. Then return true iff node_ points to a
+ // Node in a list.
+ bool revalidate_if_necessary() {
+ GOOGLE_DCHECK(node_ != NULL && m_ != NULL);
+ // Force bucket_index_ to be in range.
+ bucket_index_ &= (m_->num_buckets_ - 1);
+ // Common case: the bucket we think is relevant points to node_.
+ if (m_->table_[bucket_index_] == static_cast<void*>(node_))
+ return true;
+ // Less common: the bucket is a linked list with node_ somewhere in it,
+ // but not at the head.
+ if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
+ Node* l = static_cast<Node*>(m_->table_[bucket_index_]);
+ while ((l = l->next) != NULL) {
+ if (l == node_) {
+ return true;
+ }
+ }
+ }
+ // Well, bucket_index_ still might be correct, but probably
+ // not. Revalidate just to be sure. This case is rare enough that we
+ // don't worry about potential optimizations, such as having a custom
+ // find-like method that compares Node* instead of const Key&.
+ iterator_base i(m_->find(*KeyPtrFromNodePtr(node_)));
+ bucket_index_ = i.bucket_index_;
+ tree_it_ = i.tree_it_;
+ return m_->TableEntryIsList(bucket_index_);
+ }
+
+ Node* node_;
+ const InnerMap* m_;
+ size_type bucket_index_;
+ TreeIterator tree_it_;
+ };
+
+ public:
+ typedef iterator_base<KeyValuePair> iterator;
+ typedef iterator_base<const KeyValuePair> const_iterator;
+
+ iterator begin() { return iterator(this); }
+ iterator end() { return iterator(); }
+ const_iterator begin() const { return const_iterator(this); }
+ const_iterator end() const { return const_iterator(); }
+
+ void clear() {
+ for (size_type b = 0; b < num_buckets_; b++) {
+ if (TableEntryIsNonEmptyList(b)) {
+ Node* node = static_cast<Node*>(table_[b]);
+ table_[b] = NULL;
+ do {
+ Node* next = node->next;
+ DestroyNode(node);
+ node = next;
+ } while (node != NULL);
+ } else if (TableEntryIsTree(b)) {
+ Tree* tree = static_cast<Tree*>(table_[b]);
+ GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0);
+ table_[b] = table_[b + 1] = NULL;
+ typename Tree::iterator tree_it = tree->begin();
+ do {
+ Node* node = NodePtrFromKeyPtr(*tree_it);
+ typename Tree::iterator next = tree_it;
+ ++next;
+ tree->erase(tree_it);
+ DestroyNode(node);
+ tree_it = next;
+ } while (tree_it != tree->end());
+ DestroyTree(tree);
+ b++;
+ }
+ }
+ num_elements_ = 0;
+ index_of_first_non_null_ = num_buckets_;
+ }
+
+ const hasher& hash_function() const { return *this; }
+
+ static size_type max_size() {
+ return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28);
+ }
+ size_type size() const { return num_elements_; }
+ bool empty() const { return size() == 0; }
+
+ iterator find(const Key& k) { return iterator(FindHelper(k).first); }
+ const_iterator find(const Key& k) const { return FindHelper(k).first; }
+
+ // In traditional C++ style, this performs "insert if not present."
+ std::pair<iterator, bool> insert(const KeyValuePair& kv) {
+ std::pair<const_iterator, size_type> p = FindHelper(kv.key());
+ // Case 1: key was already present.
+ if (p.first.node_ != NULL)
+ return std::make_pair(iterator(p.first), false);
+ // Case 2: insert.
+ if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+ p = FindHelper(kv.key());
+ }
+ const size_type b = p.second; // bucket number
+ Node* node = Alloc<Node>(1);
+ alloc_.construct(&node->kv, kv);
+ iterator result = InsertUnique(b, node);
+ ++num_elements_;
+ return std::make_pair(result, true);
+ }
+
+ // The same, but if an insertion is necessary then the value portion of the
+ // inserted key-value pair is left uninitialized.
+ std::pair<iterator, bool> insert(const Key& k) {
+ std::pair<const_iterator, size_type> p = FindHelper(k);
+ // Case 1: key was already present.
+ if (p.first.node_ != NULL)
+ return std::make_pair(iterator(p.first), false);
+ // Case 2: insert.
+ if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
+ p = FindHelper(k);
+ }
+ const size_type b = p.second; // bucket number
+ Node* node = Alloc<Node>(1);
+ typedef typename Allocator::template rebind<Key>::other KeyAllocator;
+ KeyAllocator(alloc_).construct(&node->kv.key(), k);
+ iterator result = InsertUnique(b, node);
+ ++num_elements_;
+ return std::make_pair(result, true);
+ }
+
+ Value& operator[](const Key& k) {
+ KeyValuePair kv(k, Value());
+ return insert(kv).first->value();
+ }
+
+ void erase(iterator it) {
+ GOOGLE_DCHECK_EQ(it.m_, this);
+ const bool is_list = it.revalidate_if_necessary();
+ size_type b = it.bucket_index_;
+ Node* const item = it.node_;
+ if (is_list) {
+ GOOGLE_DCHECK(TableEntryIsNonEmptyList(b));
+ Node* head = static_cast<Node*>(table_[b]);
+ head = EraseFromLinkedList(item, head);
+ table_[b] = static_cast<void*>(head);
+ } else {
+ GOOGLE_DCHECK(TableEntryIsTree(b));
+ Tree* tree = static_cast<Tree*>(table_[b]);
+ tree->erase(it.tree_it_);
+ if (tree->empty()) {
+ // Force b to be the minimum of b and b ^ 1. This is important
+ // only because we want index_of_first_non_null_ to be correct.
+ b &= ~static_cast<size_type>(1);
+ DestroyTree(tree);
+ table_[b] = table_[b + 1] = NULL;
+ }
+ }
+ DestroyNode(item);
+ --num_elements_;
+ if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) {
+ while (index_of_first_non_null_ < num_buckets_ &&
+ table_[index_of_first_non_null_] == NULL) {
+ ++index_of_first_non_null_;
+ }
+ }
+ }
+
+ private:
+ std::pair<const_iterator, size_type> FindHelper(const Key& k) const {
+ size_type b = BucketNumber(k);
+ if (TableEntryIsNonEmptyList(b)) {
+ Node* node = static_cast<Node*>(table_[b]);
+ do {
+ if (IsMatch(*KeyPtrFromNodePtr(node), k)) {
+ return std::make_pair(const_iterator(node, this, b), b);
+ } else {
+ node = node->next;
+ }
+ } while (node != NULL);
+ } else if (TableEntryIsTree(b)) {
+ GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+ b &= ~static_cast<size_t>(1);
+ Tree* tree = static_cast<Tree*>(table_[b]);
+ Key* key = const_cast<Key*>(&k);
+ typename Tree::iterator tree_it = tree->find(key);
+ if (tree_it != tree->end()) {
+ return std::make_pair(const_iterator(tree_it, this, b), b);
+ }
+ }
+ return std::make_pair(end(), b);
+ }
+
+ // Insert the given Node in bucket b. If that would make bucket b too big,
+ // and bucket b is not a tree, create a tree for buckets b and b^1 to share.
+ // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
+ // bucket. num_elements_ is not modified.
+ iterator InsertUnique(size_type b, Node* node) {
+ GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ ||
+ table_[index_of_first_non_null_] != NULL);
+ // In practice, the code that led to this point may have already
+ // determined whether we are inserting into an empty list, a short list,
+ // or whatever. But it's probably cheap enough to recompute that here;
+ // it's likely that we're inserting into an empty or short list.
+ iterator result;
+ GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end());
+ if (TableEntryIsEmpty(b)) {
+ result = InsertUniqueInList(b, node);
+ } else if (TableEntryIsNonEmptyList(b)) {
+ if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) {
+ TreeConvert(b);
+ result = InsertUniqueInTree(b, node);
+ GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1));
+ } else {
+ // Insert into a pre-existing list. This case cannot modify
+ // index_of_first_non_null_, so we skip the code to update it.
+ return InsertUniqueInList(b, node);
+ }
+ } else {
+ // Insert into a pre-existing tree. This case cannot modify
+ // index_of_first_non_null_, so we skip the code to update it.
+ return InsertUniqueInTree(b, node);
+ }
+ index_of_first_non_null_ =
+ std::min(index_of_first_non_null_, result.bucket_index_);
+ return result;
+ }
+
+ // Helper for InsertUnique. Handles the case where bucket b is a
+ // not-too-long linked list.
+ iterator InsertUniqueInList(size_type b, Node* node) {
+ node->next = static_cast<Node*>(table_[b]);
+ table_[b] = static_cast<void*>(node);
+ return iterator(node, this, b);
+ }
+
+ // Helper for InsertUnique. Handles the case where bucket b points to a
+ // Tree.
+ iterator InsertUniqueInTree(size_type b, Node* node) {
+ GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
+ // Maintain the invariant that node->next is NULL for all Nodes in Trees.
+ node->next = NULL;
+ return iterator(static_cast<Tree*>(table_[b])
+ ->insert(KeyPtrFromNodePtr(node))
+ .first,
+ this, b & ~static_cast<size_t>(1));
+ }
+
+ // Returns whether it did resize. Currently this is only used when
+ // num_elements_ increases, though it could be used in other situations.
+ // It checks for load too low as well as load too high: because any number
+ // of erases can occur between inserts, the load could be as low as 0 here.
+ // Resizing to a lower size is not always helpful, but failing to do so can
+ // destroy the expected big-O bounds for some operations. By having the
+ // policy that sometimes we resize down as well as up, clients can easily
+ // keep O(size()) = O(number of buckets) if they want that.
+ bool ResizeIfLoadIsOutOfRange(size_type new_size) {
+ const size_type kMaxMapLoadTimes16 = 12; // controls RAM vs CPU tradeoff
+ const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
+ const size_type lo_cutoff = hi_cutoff / 4;
+ // We don't care how many elements are in trees. If a lot are,
+ // we may resize even though there are many empty buckets. In
+ // practice, this seems fine.
+ if (GOOGLE_PREDICT_FALSE(new_size >= hi_cutoff)) {
+ if (num_buckets_ <= max_size() / 2) {
+ Resize(num_buckets_ * 2);
+ return true;
+ }
+ } else if (GOOGLE_PREDICT_FALSE(new_size <= lo_cutoff &&
+ num_buckets_ > kMinTableSize)) {
+ size_type lg2_of_size_reduction_factor = 1;
+ // It's possible we want to shrink a lot here... size() could even be 0.
+ // So, estimate how much to shrink by making sure we don't shrink so
+ // much that we would need to grow the table after a few inserts.
+ const size_type hypothetical_size = new_size * 5 / 4 + 1;
+ while ((hypothetical_size << lg2_of_size_reduction_factor) <
+ hi_cutoff) {
+ ++lg2_of_size_reduction_factor;
+ }
+ size_type new_num_buckets = std::max<size_type>(
+ kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
+ if (new_num_buckets != num_buckets_) {
+ Resize(new_num_buckets);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Resize to the given number of buckets.
+ void Resize(size_t new_num_buckets) {
+ GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize);
+ void** const old_table = table_;
+ const size_type old_table_size = num_buckets_;
+ num_buckets_ = new_num_buckets;
+ table_ = CreateEmptyTable(num_buckets_);
+ const size_type start = index_of_first_non_null_;
+ index_of_first_non_null_ = num_buckets_;
+ for (size_type i = start; i < old_table_size; i++) {
+ if (TableEntryIsNonEmptyList(old_table, i)) {
+ TransferList(old_table, i);
+ } else if (TableEntryIsTree(old_table, i)) {
+ TransferTree(old_table, i++);
+ }
+ }
+ Dealloc<void*>(old_table, old_table_size);
+ }
+
+ void TransferList(void* const* table, size_type index) {
+ Node* node = static_cast<Node*>(table[index]);
+ do {
+ Node* next = node->next;
+ InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node);
+ node = next;
+ } while (node != NULL);
+ }
+
+ void TransferTree(void* const* table, size_type index) {
+ Tree* tree = static_cast<Tree*>(table[index]);
+ typename Tree::iterator tree_it = tree->begin();
+ do {
+ Node* node = NodePtrFromKeyPtr(*tree_it);
+ InsertUnique(BucketNumber(**tree_it), node);
+ } while (++tree_it != tree->end());
+ DestroyTree(tree);
+ }
+
+ Node* EraseFromLinkedList(Node* item, Node* head) {
+ if (head == item) {
+ return head->next;
+ } else {
+ head->next = EraseFromLinkedList(item, head->next);
+ return head;
+ }
+ }
+
+ bool TableEntryIsEmpty(size_type b) const {
+ return TableEntryIsEmpty(table_, b);
+ }
+ bool TableEntryIsNonEmptyList(size_type b) const {
+ return TableEntryIsNonEmptyList(table_, b);
+ }
+ bool TableEntryIsTree(size_type b) const {
+ return TableEntryIsTree(table_, b);
+ }
+ bool TableEntryIsList(size_type b) const {
+ return TableEntryIsList(table_, b);
+ }
+ static bool TableEntryIsEmpty(void* const* table, size_type b) {
+ return table[b] == NULL;
+ }
+ static bool TableEntryIsNonEmptyList(void* const* table, size_type b) {
+ return table[b] != NULL && table[b] != table[b ^ 1];
+ }
+ static bool TableEntryIsTree(void* const* table, size_type b) {
+ return !TableEntryIsEmpty(table, b) &&
+ !TableEntryIsNonEmptyList(table, b);
+ }
+ static bool TableEntryIsList(void* const* table, size_type b) {
+ return !TableEntryIsTree(table, b);
+ }
+
+ void TreeConvert(size_type b) {
+ GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
+ typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+ Tree* tree = tree_allocator.allocate(1);
+ // We want to use the three-arg form of construct, if it exists, but we
+ // create a temporary and use the two-arg construct that's known to exist.
+ // It's clunky, but the compiler should be able to generate more-or-less
+ // the same code.
+ tree_allocator.construct(tree,
+ Tree(KeyCompare(), KeyPtrAllocator(alloc_)));
+ // Now the tree is ready to use.
+ size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree);
+ GOOGLE_DCHECK_EQ(count, tree->size());
+ table_[b] = table_[b ^ 1] = static_cast<void*>(tree);
+ }
+
+ // Copy a linked list in the given bucket to a tree.
+ // Returns the number of things it copied.
+ size_type CopyListToTree(size_type b, Tree* tree) {
+ size_type count = 0;
+ Node* node = static_cast<Node*>(table_[b]);
+ while (node != NULL) {
+ tree->insert(KeyPtrFromNodePtr(node));
+ ++count;
+ Node* next = node->next;
+ node->next = NULL;
+ node = next;
+ }
+ return count;
+ }
+
+ // Return whether table_[b] is a linked list that seems awfully long.
+ // Requires table_[b] to point to a non-empty linked list.
+ bool TableEntryIsTooLong(size_type b) {
+ const int kMaxLength = 8;
+ size_type count = 0;
+ Node* node = static_cast<Node*>(table_[b]);
+ do {
+ ++count;
+ node = node->next;
+ } while (node != NULL);
+ // Invariant: no linked list ever is more than kMaxLength in length.
+ GOOGLE_DCHECK_LE(count, kMaxLength);
+ return count >= kMaxLength;
+ }
+
+ size_type BucketNumber(const Key& k) const {
+ // We inherit from hasher, so one-arg operator() provides a hash function.
+ size_type h = (*const_cast<InnerMap*>(this))(k);
+ // To help prevent people from making assumptions about the hash function,
+ // we use the seed differently depending on NDEBUG. The default hash
+ // function, the seeding, etc., are all likely to change in the future.
+#ifndef NDEBUG
+ return (h * (seed_ | 1)) & (num_buckets_ - 1);
+#else
+ return (h + seed_) & (num_buckets_ - 1);
+#endif
+ }
+
+ bool IsMatch(const Key& k0, const Key& k1) const {
+ return std::equal_to<Key>()(k0, k1);
+ }
+
+ // Return a power of two no less than max(kMinTableSize, n).
+ // Assumes either n < kMinTableSize or n is a power of two.
+ size_type TableSize(size_type n) {
+ return n < kMinTableSize ? kMinTableSize : n;
+ }
+
+ // Use alloc_ to allocate an array of n objects of type U.
+ template <typename U>
+ U* Alloc(size_type n) {
+ typedef typename Allocator::template rebind<U>::other alloc_type;
+ return alloc_type(alloc_).allocate(n);
+ }
+
+ // Use alloc_ to deallocate an array of n objects of type U.
+ template <typename U>
+ void Dealloc(U* t, size_type n) {
+ typedef typename Allocator::template rebind<U>::other alloc_type;
+ alloc_type(alloc_).deallocate(t, n);
+ }
+
+ void DestroyNode(Node* node) {
+ alloc_.destroy(&node->kv);
+ Dealloc<Node>(node, 1);
+ }
+
+ void DestroyTree(Tree* tree) {
+ typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
+ tree_allocator.destroy(tree);
+ tree_allocator.deallocate(tree, 1);
+ }
+
+ void** CreateEmptyTable(size_type n) {
+ GOOGLE_DCHECK(n >= kMinTableSize);
+ GOOGLE_DCHECK_EQ(n & (n - 1), 0);
+ void** result = Alloc<void*>(n);
+ memset(result, 0, n * sizeof(result[0]));
+ return result;
+ }
+
+ // Return a randomish value.
+ size_type Seed() const {
+ // random_device can throw, so avoid it unless we are compiling with
+ // exceptions enabled.
+#if __cpp_exceptions && LANG_CXX11
+ try {
+ std::random_device rd;
+ std::knuth_b knuth(rd());
+ std::uniform_int_distribution<size_type> u;
+ return u(knuth);
+ } catch (...) { }
+#endif
+ size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
+#if defined(__x86_64__) && defined(__GNUC__)
+ uint32 hi, lo;
+ asm("rdtsc" : "=a" (lo), "=d" (hi));
+ s += ((static_cast<uint64>(hi) << 32) | lo);
+#endif
+ return s;
+ }
+
+ size_type num_elements_;
+ size_type num_buckets_;
+ size_type seed_;
+ size_type index_of_first_non_null_;
+ void** table_; // an array with num_buckets_ entries
+ Allocator alloc_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap);
+ }; // end of class InnerMap
+
+ typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+ MapAllocator<std::pair<const Key, MapPair<Key, T>*> > >
+ DeprecatedInnerMap;
public:
// Iterators
+ class iterator_base {
+ public:
+ // We support "old style" and "new style" iterators for now. This is
+ // temporary. Also, for "iterator()" we have an unknown category.
+ // TODO(gpike): get rid of this.
+ enum IteratorStyle { kUnknown, kOld, kNew };
+ explicit iterator_base(IteratorStyle style) : iterator_style_(style) {}
+
+ bool OldStyle() const {
+ GOOGLE_DCHECK_NE(iterator_style_, kUnknown);
+ return iterator_style_ == kOld;
+ }
+ bool UnknownStyle() const {
+ return iterator_style_ == kUnknown;
+ }
+ bool SameStyle(const iterator_base& other) const {
+ return iterator_style_ == other.iterator_style_;
+ }
+
+ private:
+ IteratorStyle iterator_style_;
+ };
+
class const_iterator
- : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
+ : private iterator_base,
+ public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
const value_type*, const value_type&> {
typedef typename InnerMap::const_iterator InnerIt;
+ typedef typename DeprecatedInnerMap::const_iterator DeprecatedInnerIt;
public:
- const_iterator() {}
- explicit const_iterator(const InnerIt& it) : it_(it) {}
+ const_iterator() : iterator_base(iterator_base::kUnknown) {}
+ explicit const_iterator(const DeprecatedInnerIt& dit)
+ : iterator_base(iterator_base::kOld), dit_(dit) {}
+ explicit const_iterator(const InnerIt& it)
+ : iterator_base(iterator_base::kNew), it_(it) {}
- const_reference operator*() const { return *it_->second; }
- const_pointer operator->() const { return it_->second; }
+ const_iterator(const const_iterator& other)
+ : iterator_base(other), it_(other.it_), dit_(other.dit_) {}
+
+ const_reference operator*() const {
+ return this->OldStyle() ? *dit_->second : *it_->value();
+ }
+ const_pointer operator->() const { return &(operator*()); }
const_iterator& operator++() {
- ++it_;
+ if (this->OldStyle())
+ ++dit_;
+ else
+ ++it_;
return *this;
}
- const_iterator operator++(int) { return const_iterator(it_++); }
+ const_iterator operator++(int) {
+ return this->OldStyle() ? const_iterator(dit_++) : const_iterator(it_++);
+ }
friend bool operator==(const const_iterator& a, const const_iterator& b) {
- return a.it_ == b.it_;
+ if (!a.SameStyle(b)) return false;
+ if (a.UnknownStyle()) return true;
+ return a.OldStyle() ? (a.dit_ == b.dit_) : (a.it_ == b.it_);
}
friend bool operator!=(const const_iterator& a, const const_iterator& b) {
- return a.it_ != b.it_;
+ return !(a == b);
}
private:
InnerIt it_;
+ DeprecatedInnerIt dit_;
};
- class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+ class iterator : private iterator_base,
+ public std::iterator<std::forward_iterator_tag, value_type> {
typedef typename InnerMap::iterator InnerIt;
+ typedef typename DeprecatedInnerMap::iterator DeprecatedInnerIt;
public:
- iterator() {}
- explicit iterator(const InnerIt& it) : it_(it) {}
-
- reference operator*() const { return *it_->second; }
- pointer operator->() const { return it_->second; }
+ iterator() : iterator_base(iterator_base::kUnknown) {}
+ explicit iterator(const DeprecatedInnerIt& dit)
+ : iterator_base(iterator_base::kOld), dit_(dit) {}
+ explicit iterator(const InnerIt& it)
+ : iterator_base(iterator_base::kNew), it_(it) {}
+
+ reference operator*() const {
+ return this->OldStyle() ? *dit_->second : *it_->value();
+ }
+ pointer operator->() const { return &(operator*()); }
iterator& operator++() {
- ++it_;
+ if (this->OldStyle())
+ ++dit_;
+ else
+ ++it_;
return *this;
}
- iterator operator++(int) { return iterator(it_++); }
+ iterator operator++(int) {
+ return this->OldStyle() ? iterator(dit_++) : iterator(it_++);
+ }
- // Implicitly convertible to const_iterator.
- operator const_iterator() const { return const_iterator(it_); }
+ // Allow implicit conversion to const_iterator.
+ operator const_iterator() const {
+ return this->OldStyle() ?
+ const_iterator(typename DeprecatedInnerMap::const_iterator(dit_)) :
+ const_iterator(typename InnerMap::const_iterator(it_));
+ }
friend bool operator==(const iterator& a, const iterator& b) {
- return a.it_ == b.it_;
+ if (!a.SameStyle(b)) return false;
+ if (a.UnknownStyle()) return true;
+ return a.OldStyle() ? a.dit_ == b.dit_ : a.it_ == b.it_;
}
friend bool operator!=(const iterator& a, const iterator& b) {
- return a.it_ != b.it_;
+ return !(a == b);
}
private:
friend class Map;
+
InnerIt it_;
+ DeprecatedInnerIt dit_;
};
- iterator begin() { return iterator(elements_.begin()); }
- iterator end() { return iterator(elements_.end()); }
- const_iterator begin() const { return const_iterator(elements_.begin()); }
- const_iterator end() const { return const_iterator(elements_.end()); }
+ iterator begin() {
+ return old_style_ ? iterator(deprecated_elements_->begin())
+ : iterator(elements_->begin());
+ }
+ iterator end() {
+ return old_style_ ? iterator(deprecated_elements_->end())
+ : iterator(elements_->end());
+ }
+ const_iterator begin() const {
+ return old_style_ ? const_iterator(deprecated_elements_->begin())
+ : const_iterator(iterator(elements_->begin()));
+ }
+ const_iterator end() const {
+ return old_style_ ? const_iterator(deprecated_elements_->end())
+ : const_iterator(iterator(elements_->end()));
+ }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
// Capacity
- size_type size() const { return elements_.size(); }
- bool empty() const { return elements_.empty(); }
+ size_type size() const {
+ return old_style_ ? deprecated_elements_->size() : elements_->size();
+ }
+ bool empty() const { return size() == 0; }
// Element access
T& operator[](const key_type& key) {
- value_type** value = &elements_[key];
+ value_type** value =
+ old_style_ ? &(*deprecated_elements_)[key] : &(*elements_)[key];
if (*value == NULL) {
*value = CreateValueTypeInternal(key);
internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
@@ -694,13 +1524,16 @@ class Map {
// Lookup
size_type count(const key_type& key) const {
- return elements_.count(key);
+ if (find(key) != end()) assert(key == find(key)->first);
+ return find(key) == end() ? 0 : 1;
}
const_iterator find(const key_type& key) const {
- return const_iterator(elements_.find(key));
+ return old_style_ ? const_iterator(deprecated_elements_->find(key))
+ : const_iterator(iterator(elements_->find(key)));
}
iterator find(const key_type& key) {
- return iterator(elements_.find(key));
+ return old_style_ ? iterator(deprecated_elements_->find(key))
+ : iterator(elements_->find(key));
}
std::pair<const_iterator, const_iterator> equal_range(
const key_type& key) const {
@@ -724,13 +1557,22 @@ class Map {
// insert
std::pair<iterator, bool> insert(const value_type& value) {
- iterator it = find(value.first);
- if (it != end()) {
- return std::pair<iterator, bool>(it, false);
+ if (old_style_) {
+ iterator it = find(value.first);
+ if (it != end()) {
+ return std::pair<iterator, bool>(it, false);
+ } else {
+ return std::pair<iterator, bool>(
+ iterator(deprecated_elements_->insert(std::pair<Key, value_type*>(
+ value.first, CreateValueTypeInternal(value))).first), true);
+ }
} else {
- return std::pair<iterator, bool>(
- iterator(elements_.insert(std::pair<Key, value_type*>(
- value.first, CreateValueTypeInternal(value))).first), true);
+ std::pair<typename InnerMap::iterator, bool> p =
+ elements_->insert(value.first);
+ if (p.second) {
+ p.first->value() = CreateValueTypeInternal(value);
+ }
+ return std::pair<iterator, bool>(iterator(p.first), p.second);
}
}
template <class InputIt>
@@ -743,33 +1585,31 @@ class Map {
}
}
- // Erase
+ // Erase and clear
size_type erase(const key_type& key) {
- typename InnerMap::iterator it = elements_.find(key);
- if (it == elements_.end()) {
+ iterator it = find(key);
+ if (it == end()) {
return 0;
} else {
- if (arena_ == NULL) delete it->second;
- elements_.erase(it);
+ erase(it);
return 1;
}
}
- void erase(iterator pos) {
- if (arena_ == NULL) delete pos.it_->second;
- elements_.erase(pos.it_);
+ iterator erase(iterator pos) {
+ if (arena_ == NULL) delete pos.operator->();
+ iterator i = pos++;
+ if (old_style_)
+ deprecated_elements_->erase(i.dit_);
+ else
+ elements_->erase(i.it_);
+ return pos;
}
void erase(iterator first, iterator last) {
- for (iterator it = first; it != last;) {
- if (arena_ == NULL) delete it.it_->second;
- elements_.erase((it++).it_);
+ while (first != last) {
+ first = erase(first);
}
}
- void clear() {
- for (iterator it = begin(); it != end(); ++it) {
- if (arena_ == NULL) delete it.it_->second;
- }
- elements_.clear();
- }
+ void clear() { erase(begin(), end()); }
// Assign
Map& operator=(const Map& other) {
@@ -780,6 +1620,13 @@ class Map {
return *this;
}
+ // Access to hasher. Currently this returns a copy, but it may
+ // be modified to return a const reference in the future.
+ hasher hash_function() const {
+ return old_style_ ? deprecated_elements_->hash_function()
+ : elements_->hash_function();
+ }
+
private:
// Set default enum value only for proto2 map field whose value is enum type.
void SetDefaultEnumValue(int default_enum_value) {
@@ -814,9 +1661,15 @@ class Map {
}
Arena* arena_;
- Allocator allocator_;
- InnerMap elements_;
int default_enum_value_;
+ // The following is a tagged union because we support two map styles
+ // for now.
+ // TODO(gpike): get rid of the old style.
+ const bool old_style_;
+ union {
+ InnerMap* elements_;
+ DeprecatedInnerMap* deprecated_elements_;
+ };
friend class ::google::protobuf::Arena;
typedef void InternalArenaConstructable_;
@@ -837,6 +1690,12 @@ struct hash<google::protobuf::MapKey> {
size_t
operator()(const google::protobuf::MapKey& map_key) const {
switch (map_key.type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Unsupported";
+ break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
return hash<string>()(map_key.GetStringValue());
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
@@ -849,11 +1708,6 @@ struct hash<google::protobuf::MapKey> {
return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
return hash<bool>()(map_key.GetBoolValue());
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
- case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
- GOOGLE_LOG(FATAL) << "Can't get here.";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return 0;
@@ -861,26 +1715,7 @@ struct hash<google::protobuf::MapKey> {
bool
operator()(const google::protobuf::MapKey& map_key1,
const google::protobuf::MapKey& map_key2) const {
- switch (map_key1.type()) {
-#define COMPARE_CPPTYPE(CPPTYPE, CPPTYPE_METHOD) \
- case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
- return map_key1.Get##CPPTYPE_METHOD##Value() < \
- map_key2.Get##CPPTYPE_METHOD##Value();
- COMPARE_CPPTYPE(STRING, String)
- COMPARE_CPPTYPE(INT64, Int64)
- COMPARE_CPPTYPE(INT32, Int32)
- COMPARE_CPPTYPE(UINT64, UInt64)
- COMPARE_CPPTYPE(UINT32, UInt32)
- COMPARE_CPPTYPE(BOOL, Bool)
-#undef COMPARE_CPPTYPE
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
- case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
- GOOGLE_LOG(FATAL) << "Can't get here.";
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return true;
+ return map_key1 < map_key2;
}
};
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index eddc95c4..49f91818 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -178,18 +178,19 @@ bool DynamicMapField::ContainsMapKey(
return iter != map.end();
}
-bool DynamicMapField::InsertMapValue(
+bool DynamicMapField::InsertOrLookupMapValue(
const MapKey& map_key, MapValueRef* val) {
- bool result = false;
-
- MapValueRef& map_val = (*MutableMap())[map_key];
- // If map_val.data_ is not set, it is newly inserted by map_[map_key].
- if (map_val.data_ == NULL) {
- result = true;
+ // Always use mutable map because users may change the map value by
+ // MapValueRef.
+ Map<MapKey, MapValueRef>* map = MutableMap();
+ Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
+ if (iter == map->end()) {
+ // Insert
+ MapValueRef& map_val = (*map)[map_key];
const FieldDescriptor* val_des =
default_entry_->GetDescriptor()->FindFieldByName("value");
map_val.SetType(val_des->cpp_type());
- // Allocate momery for the inserted MapValueRef, and initialize to
+ // Allocate memory for the inserted MapValueRef, and initialize to
// default value.
switch (val_des->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, TYPE) \
@@ -216,9 +217,13 @@ bool DynamicMapField::InsertMapValue(
break;
}
}
+ val->CopyFrom(map_val);
+ return true;
}
- val->CopyFrom(map_val);
- return result;
+ // map_key is already in the map. Make sure (*map)[map_key] is not called.
+ // [] may reorder the map and iterators.
+ val->CopyFrom(iter->second);
+ return false;
}
bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 9130166b..4b46f3aa 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -87,7 +87,8 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
// Pure virtual map APIs for Map Reflection.
virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
- virtual bool InsertMapValue(const MapKey& map_key, MapValueRef* val) = 0;
+ virtual bool InsertOrLookupMapValue(
+ const MapKey& map_key, MapValueRef* val) = 0;
virtual bool DeleteMapValue(const MapKey& map_key) = 0;
virtual bool EqualIterator(const MapIterator& a,
const MapIterator& b) const = 0;
@@ -251,7 +252,7 @@ class MapField : public TypeDefinedMapFieldBase<Key, T>,
// Implement MapFieldBase
bool ContainsMapKey(const MapKey& map_key) const;
- bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
bool DeleteMapValue(const MapKey& map_key);
// Accessors
@@ -302,7 +303,7 @@ class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey,
// Implement MapFieldBase
bool ContainsMapKey(const MapKey& map_key) const;
- bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
bool DeleteMapValue(const MapKey& map_key);
const Map<MapKey, MapValueRef>& GetMap() const;
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index f116697c..01c9b89a 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -262,16 +262,22 @@ template <typename Key, typename T,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
bool MapField<Key, T, kKeyFieldType, kValueFieldType,
- default_enum_value>::InsertMapValue(const MapKey& map_key,
- MapValueRef* val) {
+ default_enum_value>::InsertOrLookupMapValue(
+ const MapKey& map_key,
+ MapValueRef* val) {
+ // Always use mutable map because users may change the map value by
+ // MapValueRef.
Map<Key, T>* map = MutableMap();
- bool result = false;
const Key& key = UnwrapMapKey<Key>(map_key);
- if (map->end() == map->find(key)) {
- result = true;
+ typename Map<Key, T>::iterator iter = map->find(key);
+ if (map->end() == iter) {
+ val->SetValue(&((*map)[key]));
+ return true;
}
- val->SetValue(&((*map)[key]));
- return result;
+ // Key is already in the map. Make sure (*map)[key] is not called.
+ // [] may reorder the map and iterators.
+ val->SetValue(&(iter->second));
+ return false;
}
template <typename Key, typename T,
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 2ff1d6bb..223d42f3 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -78,7 +78,7 @@ class MapFieldBaseStub : public MapFieldBase {
bool ContainsMapKey(const MapKey& map_key) const {
return false;
}
- bool InsertMapValue(const MapKey& map_key, MapValueRef* val) {
+ bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) {
return false;
}
bool DeleteMapValue(const MapKey& map_key) {
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 451b02e8..9d4d6c13 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -28,12 +28,24 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// A hack to include windows.h first, which ensures the GetMessage macro can
+// be undefined when we include <google/protobuf/stubs/common.h>
+#if defined(_WIN32)
+#define _WINSOCKAPI_ // to avoid re-definition in WinSock2.h
+#define NOMINMAX // to avoid defining min/max macros
+#include <windows.h>
+#endif // _WIN32
+
+#include <algorithm>
+#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <sstream>
+#include <vector>
#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/logging.h>
@@ -62,6 +74,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/util/time_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
@@ -79,10 +92,11 @@ namespace internal {
// Map API Test =====================================================
-class MapImplTest : public ::testing::Test {
+// Parameterized tests on whether to use old style maps.
+class MapImplTest : public testing::TestWithParam<bool> {
protected:
MapImplTest()
- : map_ptr_(new Map<int32, int32>),
+ : map_ptr_(new Map<int32, int32>(GetParam())),
map_(*map_ptr_),
const_map_(*map_ptr_) {
EXPECT_TRUE(map_.empty());
@@ -159,7 +173,7 @@ class MapImplTest : public ::testing::Test {
const Map<int32, int32>& const_map_;
};
-TEST_F(MapImplTest, OperatorBracket) {
+TEST_P(MapImplTest, OperatorBracket) {
int32 key = 0;
int32 value1 = 100;
int32 value2 = 101;
@@ -173,7 +187,7 @@ TEST_F(MapImplTest, OperatorBracket) {
ExpectSingleElement(key, value2);
}
-TEST_F(MapImplTest, OperatorBracketNonExist) {
+TEST_P(MapImplTest, OperatorBracketNonExist) {
int32 key = 0;
int32 default_value = 0;
@@ -181,7 +195,7 @@ TEST_F(MapImplTest, OperatorBracketNonExist) {
ExpectSingleElement(key, default_value);
}
-TEST_F(MapImplTest, MutableAt) {
+TEST_P(MapImplTest, MutableAt) {
int32 key = 0;
int32 value1 = 100;
int32 value2 = 101;
@@ -195,15 +209,15 @@ TEST_F(MapImplTest, MutableAt) {
#ifdef PROTOBUF_HAS_DEATH_TEST
-TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
+TEST_P(MapImplTest, MutableAtNonExistDeathTest) {
EXPECT_DEATH(map_.at(0), "");
}
-TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
+TEST_P(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
-TEST_F(MapImplTest, UsageErrors) {
+TEST_P(MapImplTest, UsageErrors) {
MapKey key;
key.SetInt64Value(1);
EXPECT_DEATH(key.GetUInt64Value(),
@@ -220,23 +234,23 @@ TEST_F(MapImplTest, UsageErrors) {
#endif // PROTOBUF_HAS_DEATH_TEST
-TEST_F(MapImplTest, CountNonExist) {
+TEST_P(MapImplTest, CountNonExist) {
EXPECT_EQ(0, map_.count(0));
}
-TEST_F(MapImplTest, MutableFindNonExist) {
+TEST_P(MapImplTest, MutableFindNonExist) {
EXPECT_TRUE(map_.end() == map_.find(0));
}
-TEST_F(MapImplTest, ImmutableFindNonExist) {
+TEST_P(MapImplTest, ImmutableFindNonExist) {
EXPECT_TRUE(const_map_.end() == const_map_.find(0));
}
-TEST_F(MapImplTest, ConstEnd) {
+TEST_P(MapImplTest, ConstEnd) {
EXPECT_TRUE(const_map_.end() == const_map_.cend());
}
-TEST_F(MapImplTest, GetReferenceFromIterator) {
+TEST_P(MapImplTest, GetReferenceFromIterator) {
for (int i = 0; i < 10; i++) {
map_[i] = i;
}
@@ -259,7 +273,7 @@ TEST_F(MapImplTest, GetReferenceFromIterator) {
}
}
-TEST_F(MapImplTest, IteratorBasic) {
+TEST_P(MapImplTest, IteratorBasic) {
map_[0] = 0;
// Default constructible (per forward iterator requirements).
@@ -281,6 +295,292 @@ TEST_F(MapImplTest, IteratorBasic) {
EXPECT_TRUE(it == cit);
}
+template <typename Iterator>
+static int64 median(Iterator i0, Iterator i1) {
+ vector<int64> v(i0, i1);
+ std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end());
+ return v[v.size() / 2];
+}
+
+static int64 Now() {
+ return google::protobuf::util::TimeUtil::TimestampToNanoseconds(
+ google::protobuf::util::TimeUtil::GetCurrentTime());
+}
+
+// Arbitrary odd integers for creating test data.
+static int k0 = 812398771;
+static int k1 = 1312938717;
+static int k2 = 1321555333;
+
+// A naive begin() implementation will cause begin() to get slower and slower
+// if one erases elements at the "front" of the hash map, and we'd like to
+// avoid that, as std::unordered_map does.
+TEST_P(MapImplTest, BeginIsFast) {
+ // Disable this test for both new and old implementations.
+ if (/*GetParam()*/true) return;
+ Map<int32, int32> map(false); // This test uses new-style maps only.
+ const int kTestSize = 250000;
+ // Create a random-looking map of size n. Use non-negative integer keys.
+ uint32 frog = 123983;
+ int last_key = 0;
+ int counter = 0;
+ while (map.size() < kTestSize) {
+ frog *= static_cast<uint32>(k0);
+ frog ^= frog >> 17;
+ frog += counter++;
+ last_key =
+ static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1;
+ GOOGLE_DCHECK_GE(last_key, 0);
+ map[last_key] = last_key ^ 1;
+ }
+ vector<int64> times;
+ // We're going to do map.erase(map.begin()) over and over again. But,
+ // just in case one iteration is fast compared to the granularity of
+ // our time keeping, we measure kChunkSize iterations per outer-loop iter.
+ const int kChunkSize = 1000;
+ GOOGLE_CHECK_EQ(kTestSize % kChunkSize, 0);
+ do {
+ const int64 start = Now();
+ for (int i = 0; i < kChunkSize; i++) {
+ map.erase(map.begin());
+ }
+ const int64 end = Now();
+ if (end > start) {
+ times.push_back(end - start);
+ }
+ } while (!map.empty());
+ if (times.size() < .99 * kTestSize / kChunkSize) {
+ GOOGLE_LOG(WARNING) << "Now() isn't helping us measure time";
+ return;
+ }
+ int64 x0 = median(times.begin(), times.begin() + 9);
+ int64 x1 = median(times.begin() + times.size() - 9, times.end());
+ GOOGLE_LOG(INFO) << "x0=" << x0 << ", x1=" << x1;
+ // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+ // And we'll probably time out and never get here. So, this test is
+ // intentionally loose: we check that x0 and x1 are within a factor of 8.
+ EXPECT_GE(x1, x0 / 8);
+ EXPECT_GE(x0, x1 / 8);
+}
+
+// Try to create kTestSize keys that will land in just a few buckets, and
+// time the insertions, to get a rough estimate of whether an O(n^2) worst case
+// was triggered. This test is a hacky, but probably better than nothing.
+TEST_P(MapImplTest, HashFlood) {
+ const int kTestSize = 1024; // must be a power of 2
+ std::set<int> s;
+ for (int i = 0; s.size() < kTestSize; i++) {
+ if ((map_.hash_function()(i) & (kTestSize - 1)) < 3) {
+ s.insert(i);
+ }
+ }
+ // Create hash table with kTestSize entries that hash flood a table with
+ // 1024 (or 512 or 2048 or ...) entries. This assumes that map_ uses powers
+ // of 2 for table sizes, and that it's sufficient to "flood" with respect to
+ // the low bits of the output of map_.hash_function().
+ vector<int64> times;
+ std::set<int>::iterator it = s.begin();
+ int count = 0;
+ do {
+ const int64 start = Now();
+ map_[*it] = 0;
+ const int64 end = Now();
+ if (end > start) {
+ times.push_back(end - start);
+ }
+ ++count;
+ ++it;
+ } while (it != s.end());
+ if (times.size() < .99 * count) return;
+ int64 x0 = median(times.begin(), times.begin() + 9);
+ int64 x1 = median(times.begin() + times.size() - 9, times.end());
+ // x1 will greatly exceed x0 if the code we just executed took O(n^2) time.
+ // But we want to allow O(n log n). A factor of 20 should be generous enough.
+ EXPECT_LE(x1, x0 * 20);
+}
+
+template <typename T, typename U>
+static void TestValidityForAllKeysExcept(int key_to_avoid,
+ const T& check_map,
+ const U& map) {
+ typedef typename U::value_type value_type; // a key-value pair
+ for (typename U::const_iterator it = map.begin(); it != map.end(); ++it) {
+ const int key = it->first;
+ if (key == key_to_avoid) continue;
+ // All iterators relevant to this key, whether old (from check_map) or new,
+ // must point to the same memory. So, test pointer equality here.
+ const value_type* check_val = &*check_map.find(key)->second;
+ EXPECT_EQ(check_val, &*it);
+ EXPECT_EQ(check_val, &*map.find(key));
+ }
+}
+
+// EXPECT i0 and i1 to be the same. Advancing them should have the same effect,
+// too.
+template <typename Iter>
+static void TestEqualIterators(Iter i0, Iter i1, Iter end) {
+ const int kMaxAdvance = 10;
+ for (int i = 0; i < kMaxAdvance; i++) {
+ EXPECT_EQ(i0 == end, i1 == end);
+ if (i0 == end) return;
+ EXPECT_EQ(&*i0, &*i1) << "iter " << i;
+ ++i0;
+ ++i1;
+ }
+}
+
+template <typename IteratorType>
+static void TestOldVersusNewIterator(int skip, Map<int, int>* m) {
+ const int initial_size = m->size();
+ IteratorType it = m->begin();
+ for (int i = 0; i < skip && it != m->end(); it++, i++) {}
+ if (it == m->end()) return;
+ const IteratorType old = it;
+ GOOGLE_LOG(INFO) << "skip=" << skip << ", old->first=" << old->first;
+ const int target_size =
+ initial_size < 100 ? initial_size * 5 : initial_size * 5 / 4;
+ for (int i = 0; m->size() <= target_size; i++) {
+ (*m)[i] = 0;
+ }
+ // Iterator 'old' should still work just fine despite the growth of *m.
+ const IteratorType after_growth = m->find(old->first);
+ TestEqualIterators<IteratorType>(old, after_growth, m->end());
+
+ // Now shrink the number of elements. Do this with a mix of erases and
+ // inserts to increase the chance that the hashtable will resize to a lower
+ // number of buckets. (But, in any case, the test is still useful.)
+ for (int i = 0; i < 2 * (target_size - initial_size); i++) {
+ if (i != old->first) {
+ m->erase(i);
+ }
+ if (((i ^ m->begin()->first) & 15) == 0) {
+ (*m)[i * 342] = i;
+ }
+ }
+ // Now, the table has grown and shrunk; test again.
+ TestEqualIterators<IteratorType>(old, m->find(old->first), m->end());
+ TestEqualIterators<IteratorType>(old, after_growth, m->end());
+}
+
+// Create and test an n-element Map, with emphasis on iterator correctness.
+static void StressTestIterators(int n, bool test_old_style_proto2_maps) {
+ GOOGLE_LOG(INFO) << "StressTestIterators " << n;
+ GOOGLE_CHECK_GT(n, 0);
+ // Create a random-looking map of size n. Use non-negative integer keys.
+ Map<int, int> m(test_old_style_proto2_maps);
+ uint32 frog = 123987 + n;
+ int last_key = 0;
+ int counter = 0;
+ while (m.size() < n) {
+ frog *= static_cast<uint32>(k0);
+ frog ^= frog >> 17;
+ frog += counter++;
+ last_key =
+ static_cast<int>(frog) >= 0 ? static_cast<int>(frog) : last_key ^ 1;
+ GOOGLE_DCHECK_GE(last_key, 0);
+ m[last_key] = last_key ^ 1;
+ }
+ // Test it.
+ ASSERT_EQ(n, m.size());
+ // Create maps of pointers and iterators.
+ // These should remain valid even if we modify m.
+ hash_map<int, Map<int, int>::value_type*> mp(n);
+ hash_map<int, Map<int, int>::iterator> mi(n);
+ for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+ mp[it->first] = &*it;
+ mi[it->first] = it;
+ }
+ ASSERT_EQ(m.size(), mi.size());
+ ASSERT_EQ(m.size(), mp.size());
+ m.erase(last_key);
+ ASSERT_EQ(n - 1, m.size());
+ TestValidityForAllKeysExcept(last_key, mp, m);
+ TestValidityForAllKeysExcept(last_key, mi, m);
+
+ m[last_key] = 0;
+ ASSERT_EQ(n, m.size());
+ // Test old iterator vs new iterator, with table modification in between.
+ TestOldVersusNewIterator<Map<int, int>::const_iterator>(n % 3, &m);
+ TestOldVersusNewIterator<Map<int, int>::iterator>(n % (1 + (n / 40)), &m);
+ // Finally, ensure erase(iterator) doesn't reorder anything, becuase that is
+ // what its documentation says.
+ m[last_key] = m[last_key ^ 999] = 0;
+ vector<Map<int, int>::iterator> v;
+ v.reserve(m.size());
+ int position_of_last_key = 0;
+ for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
+ if (it->first == last_key) {
+ position_of_last_key = v.size();
+ }
+ v.push_back(it);
+ }
+ ASSERT_EQ(m.size(), v.size());
+ const Map<int, int>::iterator erase_result = m.erase(m.find(last_key));
+ int index = 0;
+ for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it, ++index) {
+ if (index == position_of_last_key) {
+ EXPECT_EQ(&*erase_result, &*v[++index]);
+ }
+ ASSERT_EQ(&*it, &*v[index]);
+ }
+}
+
+TEST_P(MapImplTest, IteratorInvalidation) {
+ // As multiple underlying hash_map implementations do not follow the
+ // validation requirement, the test is disabled for old-style maps.
+ if (GetParam()) return;
+ // Create a set of pseudo-random sizes to test.
+#ifndef NDEBUG
+ const int kMaxSizeToTest = 100 * 1000;
+#else
+ const int kMaxSizeToTest = 1000 * 1000;
+#endif
+ std::set<int> s;
+ int n = kMaxSizeToTest;
+ int frog = k1 + n;
+ while (n > 1 && s.size() < 25) {
+ s.insert(n);
+ n = static_cast<int>(n * 100 / (101.0 + (frog & 63)));
+ frog *= k2;
+ frog ^= frog >> 17;
+ }
+ // Ensure we test a few small sizes.
+ s.insert(1);
+ s.insert(2);
+ s.insert(3);
+ // Now, the real work.
+ for (std::set<int>::iterator i = s.begin(); i != s.end(); ++i) {
+ StressTestIterators(*i, GetParam());
+ }
+}
+
+// Test that erase() revalidates iterators.
+TEST_P(MapImplTest, EraseRevalidates) {
+ // As multiple underlying hash_map implementations do not follow the
+ // validation requirement, the test is disabled for old-style maps.
+ if (GetParam()) return;
+ map_[3] = map_[13] = map_[20] = 0;
+ const int initial_size = map_.size();
+ EXPECT_EQ(3, initial_size);
+ vector<Map<int, int>::iterator> v;
+ for (Map<int, int>::iterator it = map_.begin(); it != map_.end(); ++it) {
+ v.push_back(it);
+ }
+ EXPECT_EQ(initial_size, v.size());
+ for (int i = 0; map_.size() <= initial_size * 20; i++) {
+ map_[i] = 0;
+ }
+ const int larger_size = map_.size();
+ // We've greatly increased the size of the map, so it is highly likely that
+ // the following will corrupt m if erase() doesn't properly revalidate
+ // iterators passed to it. Finishing this routine without crashing indicates
+ // success.
+ for (int i = 0; i < v.size(); i++) {
+ map_.erase(v[i]);
+ }
+ EXPECT_EQ(larger_size - v.size(), map_.size());
+}
+
template <typename T>
bool IsConstHelper(T& /*t*/) { // NOLINT. We want to catch non-const refs here.
return false;
@@ -290,7 +590,7 @@ bool IsConstHelper(const T& /*t*/) {
return true;
}
-TEST_F(MapImplTest, IteratorConstness) {
+TEST_P(MapImplTest, IteratorConstness) {
map_[0] = 0;
EXPECT_TRUE(IsConstHelper(*map_.cbegin()));
EXPECT_TRUE(IsConstHelper(*const_map_.begin()));
@@ -303,14 +603,14 @@ bool IsForwardIteratorHelper(T /*t*/) {
return false;
}
-TEST_F(MapImplTest, IteratorCategory) {
+TEST_P(MapImplTest, IteratorCategory) {
EXPECT_TRUE(IsForwardIteratorHelper(
std::iterator_traits<Map<int, int>::iterator>::iterator_category()));
EXPECT_TRUE(IsForwardIteratorHelper(std::iterator_traits<
Map<int, int>::const_iterator>::iterator_category()));
}
-TEST_F(MapImplTest, InsertSingle) {
+TEST_P(MapImplTest, InsertSingle) {
int32 key = 0;
int32 value1 = 100;
int32 value2 = 101;
@@ -335,7 +635,7 @@ TEST_F(MapImplTest, InsertSingle) {
EXPECT_FALSE(result2.second);
}
-TEST_F(MapImplTest, InsertByIterator) {
+TEST_P(MapImplTest, InsertByIterator) {
int32 key1 = 0;
int32 key2 = 1;
int32 value1a = 100;
@@ -358,7 +658,7 @@ TEST_F(MapImplTest, InsertByIterator) {
ExpectElements(map1);
}
-TEST_F(MapImplTest, EraseSingleByKey) {
+TEST_P(MapImplTest, EraseSingleByKey) {
int32 key = 0;
int32 value = 100;
@@ -376,7 +676,7 @@ TEST_F(MapImplTest, EraseSingleByKey) {
EXPECT_EQ(0, map_.erase(key));
}
-TEST_F(MapImplTest, EraseMutipleByKey) {
+TEST_P(MapImplTest, EraseMutipleByKey) {
// erase in one specific order to trigger corner cases
for (int i = 0; i < 5; i++) {
map_[i] = i;
@@ -403,7 +703,7 @@ TEST_F(MapImplTest, EraseMutipleByKey) {
EXPECT_TRUE(map_.end() == map_.find(2));
}
-TEST_F(MapImplTest, EraseSingleByIterator) {
+TEST_P(MapImplTest, EraseSingleByIterator) {
int32 key = 0;
int32 value = 100;
@@ -418,7 +718,7 @@ TEST_F(MapImplTest, EraseSingleByIterator) {
EXPECT_TRUE(map_.begin() == map_.end());
}
-TEST_F(MapImplTest, ValidIteratorAfterErase) {
+TEST_P(MapImplTest, ValidIteratorAfterErase) {
for (int i = 0; i < 10; i++) {
map_[i] = i;
}
@@ -438,7 +738,7 @@ TEST_F(MapImplTest, ValidIteratorAfterErase) {
EXPECT_EQ(5, map_.size());
}
-TEST_F(MapImplTest, EraseByIterator) {
+TEST_P(MapImplTest, EraseByIterator) {
int32 key1 = 0;
int32 key2 = 1;
int32 value1 = 100;
@@ -459,7 +759,7 @@ TEST_F(MapImplTest, EraseByIterator) {
EXPECT_TRUE(map_.begin() == map_.end());
}
-TEST_F(MapImplTest, Clear) {
+TEST_P(MapImplTest, Clear) {
int32 key = 0;
int32 value = 100;
@@ -474,7 +774,7 @@ TEST_F(MapImplTest, Clear) {
EXPECT_TRUE(map_.begin() == map_.end());
}
-TEST_F(MapImplTest, CopyConstructor) {
+static void CopyConstructorHelper(Arena* arena, Map<int32, int32>* m) {
int32 key1 = 0;
int32 key2 = 1;
int32 value1 = 100;
@@ -484,16 +784,25 @@ TEST_F(MapImplTest, CopyConstructor) {
map[key1] = value1;
map[key2] = value2;
- map_.insert(map.begin(), map.end());
+ m->insert(map.begin(), map.end());
- Map<int32, int32> other(map_);
+ Map<int32, int32> other(*m);
EXPECT_EQ(2, other.size());
EXPECT_EQ(value1, other.at(key1));
EXPECT_EQ(value2, other.at(key2));
}
-TEST_F(MapImplTest, IterConstructor) {
+TEST_P(MapImplTest, CopyConstructorWithArena) {
+ Arena a;
+ CopyConstructorHelper(&a, &map_);
+}
+
+TEST_P(MapImplTest, CopyConstructorWithoutArena) {
+ CopyConstructorHelper(NULL, &map_);
+}
+
+TEST_P(MapImplTest, IterConstructor) {
int32 key1 = 0;
int32 key2 = 1;
int32 value1 = 100;
@@ -503,14 +812,15 @@ TEST_F(MapImplTest, IterConstructor) {
map[key1] = value1;
map[key2] = value2;
- Map<int32, int32> new_map(map.begin(), map.end());
+ Map<int32, int32> new_map(map.begin(), map.end(),
+ GetParam());
EXPECT_EQ(2, new_map.size());
EXPECT_EQ(value1, new_map.at(key1));
EXPECT_EQ(value2, new_map.at(key2));
}
-TEST_F(MapImplTest, Assigner) {
+TEST_P(MapImplTest, Assigner) {
int32 key1 = 0;
int32 key2 = 1;
int32 value1 = 100;
@@ -522,7 +832,7 @@ TEST_F(MapImplTest, Assigner) {
map_.insert(map.begin(), map.end());
- Map<int32, int32> other;
+ Map<int32, int32> other(GetParam());
int32 key_other = 123;
int32 value_other = 321;
other[key_other] = value_other;
@@ -540,9 +850,16 @@ TEST_F(MapImplTest, Assigner) {
EXPECT_EQ(2, other.size());
EXPECT_EQ(value1, other.at(key1));
EXPECT_EQ(value2, other.at(key2));
+
+ // Try assignment to a map with a different choice of "style."
+ Map<int32, int32> m(!GetParam());
+ m = other;
+ EXPECT_EQ(2, m.size());
+ EXPECT_EQ(value1, m.at(key1));
+ EXPECT_EQ(value2, m.at(key2));
}
-TEST_F(MapImplTest, Rehash) {
+TEST_P(MapImplTest, Rehash) {
const int test_size = 50;
std::map<int32, int32> reference_map;
for (int i = 0; i < test_size; i++) {
@@ -559,7 +876,7 @@ TEST_F(MapImplTest, Rehash) {
EXPECT_TRUE(map_.empty());
}
-TEST_F(MapImplTest, EqualRange) {
+TEST_P(MapImplTest, EqualRange) {
int key = 100, key_missing = 101;
map_[key] = 100;
@@ -583,14 +900,14 @@ TEST_F(MapImplTest, EqualRange) {
EXPECT_TRUE(const_map_.end() == const_range.second);
}
-TEST_F(MapImplTest, ConvertToStdMap) {
+TEST_P(MapImplTest, ConvertToStdMap) {
map_[100] = 101;
std::map<int32, int32> std_map(map_.begin(), map_.end());
EXPECT_EQ(1, std_map.size());
EXPECT_EQ(101, std_map[100]);
}
-TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
+TEST_P(MapImplTest, ConvertToStdVectorOfPairs) {
map_[100] = 101;
std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
EXPECT_EQ(1, std_vec.size());
@@ -598,6 +915,8 @@ TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
EXPECT_EQ(101, std_vec[0].second);
}
+INSTANTIATE_TEST_CASE_P(BoolSequence, MapImplTest, testing::Bool());
+
// Map Field Reflection Test ========================================
static int Func(int i, int j) {
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 032748bd..d62ca79c 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -69,7 +69,7 @@ void Message::MergeFrom(const Message& from) {
GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
<< ": Tried to merge from a message with a different type. "
"to: " << descriptor->full_name() << ", "
- "from:" << from.GetDescriptor()->full_name();
+ "from: " << from.GetDescriptor()->full_name();
ReflectionOps::Merge(from, this);
}
@@ -82,7 +82,7 @@ void Message::CopyFrom(const Message& from) {
GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
<< ": Tried to copy from a message with a different type. "
"to: " << descriptor->full_name() << ", "
- "from:" << from.GetDescriptor()->full_name();
+ "from: " << from.GetDescriptor()->full_name();
ReflectionOps::Copy(from, this);
}
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 5bd8bcfb..9d7b64f7 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -62,13 +62,15 @@ namespace {
// provide a useful error message.
void ByteSizeConsistencyError(int byte_size_before_serialization,
int byte_size_after_serialization,
- int bytes_produced_by_serialization) {
+ int bytes_produced_by_serialization,
+ const MessageLite& message) {
GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
- << "Protocol message was modified concurrently during serialization.";
+ << message.GetTypeName()
+ << " was modified concurrently during serialization.";
GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
<< "Byte size calculation and serialization were inconsistent. This "
"may indicate a bug in protocol buffers or it may be caused by "
- "concurrent modification of the message.";
+ "concurrent modification of " << message.GetTypeName() << ".";
GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
}
@@ -248,7 +250,7 @@ bool MessageLite::SerializePartialToCodedStream(
if (buffer != NULL) {
uint8* end = SerializeWithCachedSizesToArray(buffer);
if (end - buffer != size) {
- ByteSizeConsistencyError(size, ByteSize(), end - buffer);
+ ByteSizeConsistencyError(size, ByteSize(), end - buffer, *this);
}
return true;
} else {
@@ -261,7 +263,7 @@ bool MessageLite::SerializePartialToCodedStream(
if (final_byte_count - original_byte_count != size) {
ByteSizeConsistencyError(size, ByteSize(),
- final_byte_count - original_byte_count);
+ final_byte_count - original_byte_count, *this);
}
return true;
@@ -299,7 +301,7 @@ bool MessageLite::AppendPartialToString(string* output) const {
reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
uint8* end = SerializeWithCachedSizesToArray(start);
if (end - start != byte_size) {
- ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
}
return true;
}
@@ -325,7 +327,7 @@ bool MessageLite::SerializePartialToArray(void* data, int size) const {
uint8* start = reinterpret_cast<uint8*>(data);
uint8* end = SerializeWithCachedSizesToArray(start);
if (end - start != byte_size) {
- ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start, *this);
}
return true;
}
@@ -359,6 +361,11 @@ void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
MessageLite* to) {
to->CheckTypeAndMergeFrom(from);
}
+template<>
+void GenericTypeHandler<string>::Merge(const string& from,
+ string* to) {
+ *to = from;
+}
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index 2d4780fe..d668a1a6 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -55,6 +55,7 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
index 219645d3..fdee150b 100644
--- a/src/google/protobuf/metadata.h
+++ b/src/google/protobuf/metadata.h
@@ -56,7 +56,7 @@ namespace internal {
// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
// pointer.
-class InternalMetadataWithArena {
+class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
public:
InternalMetadataWithArena() : ptr_(NULL) {}
explicit InternalMetadataWithArena(Arena* arena)
diff --git a/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/google/protobuf/proto3_arena_lite_unittest.cc
new file mode 100644
index 00000000..0f18c027
--- /dev/null
+++ b/src/google/protobuf/proto3_arena_lite_unittest.cc
@@ -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.
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena_lite.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_arena_lite_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of arena support.
+void SetAllFields(TestAllTypes* m) {
+ m->set_optional_int32(100);
+ m->set_optional_string("asdf");
+ m->set_optional_bytes("jkl;");
+ m->mutable_optional_nested_message()->set_bb(42);
+ m->mutable_optional_foreign_message()->set_c(43);
+ m->set_optional_nested_enum(
+ proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->set_optional_foreign_enum(
+ proto3_arena_lite_unittest::FOREIGN_BAZ);
+ m->mutable_optional_lazy_message()->set_bb(45);
+ m->add_repeated_int32(100);
+ m->add_repeated_string("asdf");
+ m->add_repeated_bytes("jkl;");
+ m->add_repeated_nested_message()->set_bb(46);
+ m->add_repeated_foreign_message()->set_c(47);
+ m->add_repeated_nested_enum(
+ proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->add_repeated_foreign_enum(
+ proto3_arena_lite_unittest::FOREIGN_BAZ);
+ m->add_repeated_lazy_message()->set_bb(49);
+
+ m->set_oneof_uint32(1);
+ m->mutable_oneof_nested_message()->set_bb(50);
+ m->set_oneof_string("test"); // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+ EXPECT_EQ(100, m.optional_int32());
+ EXPECT_EQ("asdf", m.optional_string());
+ EXPECT_EQ("jkl;", m.optional_bytes());
+ EXPECT_EQ(true, m.has_optional_nested_message());
+ EXPECT_EQ(42, m.optional_nested_message().bb());
+ EXPECT_EQ(true, m.has_optional_foreign_message());
+ EXPECT_EQ(43, m.optional_foreign_message().c());
+ EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.optional_nested_enum());
+ EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ,
+ m.optional_foreign_enum());
+ EXPECT_EQ(true, m.has_optional_lazy_message());
+ EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+ EXPECT_EQ(1, m.repeated_int32_size());
+ EXPECT_EQ(100, m.repeated_int32(0));
+ EXPECT_EQ(1, m.repeated_string_size());
+ EXPECT_EQ("asdf", m.repeated_string(0));
+ EXPECT_EQ(1, m.repeated_bytes_size());
+ EXPECT_EQ("jkl;", m.repeated_bytes(0));
+ EXPECT_EQ(1, m.repeated_nested_message_size());
+ EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+ EXPECT_EQ(1, m.repeated_foreign_message_size());
+ EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+ EXPECT_EQ(1, m.repeated_nested_enum_size());
+ EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.repeated_nested_enum(0));
+ EXPECT_EQ(1, m.repeated_foreign_enum_size());
+ EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ,
+ m.repeated_foreign_enum(0));
+ EXPECT_EQ(1, m.repeated_lazy_message_size());
+ EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+ EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes::kOneofString,
+ m.oneof_field_case());
+ EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of arena support in
+// proto3 and expect the arena support to be fully tested in proto2 unittests
+// because proto3 shares most code with proto2.
+
+TEST(Proto3ArenaLiteTest, Parsing) {
+ TestAllTypes original;
+ SetAllFields(&original);
+
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->ParseFromString(original.SerializeAsString());
+ ExpectAllFieldsSet(*arena_message);
+}
+
+TEST(Proto3ArenaLiteTest, Swap) {
+ Arena arena1;
+ Arena arena2;
+
+ // Test Swap().
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ arena1_message->Swap(arena2_message);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+}
+
+TEST(Proto3ArenaLiteTest, SetAllocatedMessage) {
+ Arena arena;
+ TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+ nested->set_bb(118);
+ arena_message->set_allocated_optional_nested_message(nested);
+ EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+}
+
+TEST(Proto3ArenaLiteTest, ReleaseMessage) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(118);
+ google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
+ arena_message->release_optional_nested_message());
+ EXPECT_EQ(118, nested->bb());
+}
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/proto3_lite_unittest.cc b/src/google/protobuf/proto3_lite_unittest.cc
new file mode 100644
index 00000000..2e2beea9
--- /dev/null
+++ b/src/google/protobuf/proto3_lite_unittest.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 <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_lite.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_lite_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of lite support.
+void SetAllFields(TestAllTypes* m) {
+ m->set_optional_int32(100);
+ m->set_optional_string("asdf");
+ m->set_optional_bytes("jkl;");
+ m->mutable_optional_nested_message()->set_bb(42);
+ m->mutable_optional_foreign_message()->set_c(43);
+ m->set_optional_nested_enum(
+ proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->set_optional_foreign_enum(
+ proto3_lite_unittest::FOREIGN_BAZ);
+ m->mutable_optional_lazy_message()->set_bb(45);
+ m->add_repeated_int32(100);
+ m->add_repeated_string("asdf");
+ m->add_repeated_bytes("jkl;");
+ m->add_repeated_nested_message()->set_bb(46);
+ m->add_repeated_foreign_message()->set_c(47);
+ m->add_repeated_nested_enum(
+ proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->add_repeated_foreign_enum(
+ proto3_lite_unittest::FOREIGN_BAZ);
+ m->add_repeated_lazy_message()->set_bb(49);
+
+ m->set_oneof_uint32(1);
+ m->mutable_oneof_nested_message()->set_bb(50);
+ m->set_oneof_string("test"); // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+ EXPECT_EQ(100, m.optional_int32());
+ EXPECT_EQ("asdf", m.optional_string());
+ EXPECT_EQ("jkl;", m.optional_bytes());
+ EXPECT_EQ(true, m.has_optional_nested_message());
+ EXPECT_EQ(42, m.optional_nested_message().bb());
+ EXPECT_EQ(true, m.has_optional_foreign_message());
+ EXPECT_EQ(43, m.optional_foreign_message().c());
+ EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.optional_nested_enum());
+ EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ,
+ m.optional_foreign_enum());
+ EXPECT_EQ(true, m.has_optional_lazy_message());
+ EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+ EXPECT_EQ(1, m.repeated_int32_size());
+ EXPECT_EQ(100, m.repeated_int32(0));
+ EXPECT_EQ(1, m.repeated_string_size());
+ EXPECT_EQ("asdf", m.repeated_string(0));
+ EXPECT_EQ(1, m.repeated_bytes_size());
+ EXPECT_EQ("jkl;", m.repeated_bytes(0));
+ EXPECT_EQ(1, m.repeated_nested_message_size());
+ EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+ EXPECT_EQ(1, m.repeated_foreign_message_size());
+ EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+ EXPECT_EQ(1, m.repeated_nested_enum_size());
+ EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.repeated_nested_enum(0));
+ EXPECT_EQ(1, m.repeated_foreign_enum_size());
+ EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ,
+ m.repeated_foreign_enum(0));
+ EXPECT_EQ(1, m.repeated_lazy_message_size());
+ EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+ EXPECT_EQ(proto3_lite_unittest::TestAllTypes::kOneofString,
+ m.oneof_field_case());
+ EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of in proto3 and expect
+// the rest is fully tested in proto2 unittests because proto3 shares most code
+// with proto2.
+
+TEST(Proto3LiteTest, Parsing) {
+ TestAllTypes original;
+ SetAllFields(&original);
+
+ TestAllTypes msg;
+ msg.ParseFromString(original.SerializeAsString());
+ ExpectAllFieldsSet(msg);
+}
+
+TEST(Proto3LiteTest, Swap) {
+ // Test Swap().
+ TestAllTypes msg1;
+ TestAllTypes msg2;
+ msg1.set_optional_string("123");
+ msg2.set_optional_string("3456");
+ msg1.Swap(&msg2);
+ EXPECT_EQ("3456", msg1.optional_string());
+ EXPECT_EQ("123", msg2.optional_string());
+ EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1);
+}
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 949e0a23..77004f59 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -52,8 +52,8 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
}
Rep* old_rep = rep_;
Arena* arena = GetArenaNoVirtual();
- new_size = max(kMinRepeatedFieldAllocationSize,
- max(total_size_ * 2, new_size));
+ new_size = std::max(kMinRepeatedFieldAllocationSize,
+ std::max(total_size_ * 2, new_size));
GOOGLE_CHECK_LE(new_size,
(std::numeric_limits<size_t>::max() - kRepHeaderSize) /
sizeof(old_rep->elements[0]))
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 5447fa42..1961bc48 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -244,7 +244,7 @@ class RepeatedField {
int total_size_;
struct Rep {
Arena* arena;
- Element elements[1];
+ Element elements[1];
};
// We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on
// the struct. We can not use sizeof(Arena*) as well because there might be
@@ -272,6 +272,22 @@ class RepeatedField {
inline Arena* GetArenaNoVirtual() const {
return (rep_ == NULL) ? NULL : rep_->arena;
}
+
+ // Internal helper to delete all elements and deallocate the storage.
+ // If Element has a trivial destructor (for example, if it's a fundamental
+ // type, like int32), the loop will be removed by the optimizer.
+ void InternalDeallocate(Rep* rep, int size) {
+ if (rep != NULL) {
+ Element* e = &rep->elements[0];
+ Element* limit = &rep->elements[size];
+ for (; e < limit; e++) {
+ e->Element::~Element();
+ }
+ if (rep->arena == NULL) {
+ delete[] reinterpret_cast<char*>(rep);
+ }
+ }
+ }
};
template<typename Element>
@@ -610,6 +626,13 @@ inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
template <>
void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
MessageLite* to);
+template<>
+inline void GenericTypeHandler<string>::Clear(string* value) {
+ value->clear();
+}
+template<>
+void GenericTypeHandler<string>::Merge(const string& from,
+ string* to);
// Declarations of the specialization as we cannot define them here, as the
// header that defines ProtocolMessage depends on types defined in this header.
@@ -836,6 +859,15 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Add an already-allocated object, skipping arena-ownership checks. The user
// must guarantee that the given object is in the same arena as this
// RepeatedPtrField.
+ // It is also useful in legacy code that uses temporary ownership to avoid
+ // copies. Example:
+ // RepeatedPtrField<T> temp_field;
+ // temp_field.AddAllocated(new T);
+ // ... // Do something with temp_field
+ // temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+ // If you put temp_field on the arena this fails, because the ownership
+ // transfers to the arena at the "AddAllocated" call and is not released
+ // anymore causing a double delete. UnsafeArenaAddAllocated prevents this.
void UnsafeArenaAddAllocated(Element* value);
// Remove the last element and return it. Works only when operating on an
@@ -992,19 +1024,8 @@ RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
template <typename Element>
RepeatedField<Element>::~RepeatedField() {
// See explanation in Reserve(): we need to invoke destructors here for the
- // case that Element has a non-trivial destructor. If Element has a trivial
- // destructor (for example, if it's a primitive type, like int32), this entire
- // loop will be removed by the optimizer.
- if (rep_ != NULL) {
- Element* e = &rep_->elements[0];
- Element* limit = &rep_->elements[total_size_];
- for (; e < limit; e++) {
- e->Element::~Element();
- }
- if (rep_->arena == NULL) {
- delete[] reinterpret_cast<char*>(rep_);
- }
- }
+ // case that Element has a non-trivial destructor.
+ InternalDeallocate(rep_, total_size_);
}
template <typename Element>
@@ -1240,8 +1261,8 @@ void RepeatedField<Element>::Reserve(int new_size) {
if (total_size_ >= new_size) return;
Rep* old_rep = rep_;
Arena* arena = GetArenaNoVirtual();
- new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
- max(total_size_ * 2, new_size));
+ new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+ std::max(total_size_ * 2, new_size));
GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
(std::numeric_limits<size_t>::max() - kRepHeaderSize) /
sizeof(Element))
@@ -1274,18 +1295,10 @@ void RepeatedField<Element>::Reserve(int new_size) {
if (current_size_ > 0) {
MoveArray(rep_->elements, old_rep->elements, current_size_);
}
- if (old_rep) {
- // Likewise, we need to invoke destructors on the old array. If Element has
- // no destructor, this loop will disappear.
- e = &old_rep->elements[0];
- limit = &old_rep->elements[old_total_size];
- for (; e < limit; e++) {
- e->Element::~Element();
- }
- if (arena == NULL) {
- delete[] reinterpret_cast<char*>(old_rep);
- }
- }
+
+ // Likewise, we need to invoke destructors on the old array.
+ InternalDeallocate(old_rep, old_total_size);
+
}
template <typename Element>
@@ -2380,6 +2393,37 @@ template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator
private:
RepeatedPtrField<T>* field_;
};
+
+// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one
+// uses the UnsafeArenaAddAllocated instead.
+template<typename T>
+class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator
+ : public std::iterator<std::output_iterator_tag, T> {
+ public:
+ explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator(
+ ::google::protobuf::RepeatedPtrField<T>* const mutable_field)
+ : field_(mutable_field) {
+ }
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
+ T const* const ptr_to_value) {
+ field_->UnsafeArenaAddAllocated(const_cast<T*>(ptr_to_value));
+ return *this;
+ }
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
+ return *this;
+ }
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
+ return *this;
+ }
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
+ int /* unused */) {
+ return *this;
+ }
+
+ private:
+ ::google::protobuf::RepeatedPtrField<T>* field_;
+};
+
} // namespace internal
// Provides a back insert iterator for RepeatedField instances,
@@ -2414,6 +2458,25 @@ AllocatedRepeatedPtrFieldBackInserter(
mutable_field);
}
+// Similar to AllocatedRepeatedPtrFieldBackInserter, using
+// UnsafeArenaAddAllocated instead of AddAllocated.
+// This is slightly faster if that matters. It is also useful in legacy code
+// that uses temporary ownership to avoid copies. Example:
+// RepeatedPtrField<T> temp_field;
+// temp_field.AddAllocated(new T);
+// ... // Do something with temp_field
+// temp_field.ExtractSubrange(0, temp_field.size(), NULL);
+// If you put temp_field on the arena this fails, because the ownership
+// transfers to the arena at the "AddAllocated" call and is not released anymore
+// causing a double delete. Using UnsafeArenaAddAllocated prevents this.
+template<typename T>
+internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>
+UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+ ::google::protobuf::RepeatedPtrField<T>* const mutable_field) {
+ return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>(
+ mutable_field);
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index b45664b0..39b24b33 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -1522,6 +1522,44 @@ TEST_F(RepeatedFieldInsertionIteratorsTest,
EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
}
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+ UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
+ vector<Nested*> data;
+ TestAllTypes goldenproto;
+ for (int i = 0; i < 10; ++i) {
+ Nested* new_data = new Nested;
+ new_data->set_bb(i);
+ data.push_back(new_data);
+
+ new_data = goldenproto.add_repeated_nested_message();
+ new_data->set_bb(i);
+ }
+ TestAllTypes testproto;
+ std::copy(data.begin(), data.end(),
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_nested_message()));
+ EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+ UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
+ vector<string*> data;
+ TestAllTypes goldenproto;
+ for (int i = 0; i < 10; ++i) {
+ string* new_data = new string;
+ *new_data = "name-" + SimpleItoa(i);
+ data.push_back(new_data);
+
+ new_data = goldenproto.add_repeated_string();
+ *new_data = "name-" + SimpleItoa(i);
+ }
+ TestAllTypes testproto;
+ std::copy(data.begin(), data.end(),
+ UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_string()));
+ EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
} // namespace
} // namespace protobuf
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index f2eb7ae7..c67cd102 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -177,12 +177,13 @@ SourceContext* SourceContext::New(::google::protobuf::Arena* arena) const {
}
void SourceContext::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
bool SourceContext::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.SourceContext)
for (;;) {
@@ -262,6 +263,7 @@ void SourceContext::SerializeWithCachedSizes(
}
int SourceContext::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext)
int total_size = 0;
// optional string file_name = 1;
@@ -278,18 +280,22 @@ int SourceContext::ByteSize() const {
}
void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const SourceContext* source =
::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext)
MergeFrom(*source);
}
}
void SourceContext::MergeFrom(const SourceContext& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.file_name().size() > 0) {
@@ -298,12 +304,14 @@ void SourceContext::MergeFrom(const SourceContext& from) {
}
void SourceContext::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void SourceContext::CopyFrom(const SourceContext& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceContext)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -365,6 +373,7 @@ void SourceContext::clear_file_name() {
return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* SourceContext::release_file_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 02e11460..ccfd365b 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -160,6 +160,7 @@ inline ::std::string* SourceContext::mutable_file_name() {
return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* SourceContext::release_file_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name)
return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index e020597a..11ccabbf 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -166,9 +166,11 @@ void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() {
"\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf."
"ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu"
"es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull"
- "Value\022\016\n\nNULL_VALUE\020\000BN\n\023com.google.prot"
- "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pr"
- "otobuf.WellKnownTypesb\006proto3", 589);
+ "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro"
+ "tobufB\013StructProtoP\001Z1github.com/golang/"
+ "protobuf/ptypes/struct;structpb\240\001\001\242\002\003GPB"
+ "\252\002\036Google.Protobuf.WellKnownTypesb\006proto"
+ "3", 641);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/struct.proto", &protobuf_RegisterTypes);
Struct::default_instance_ = new Struct();
@@ -280,12 +282,13 @@ Struct* Struct::New(::google::protobuf::Arena* arena) const {
}
void Struct::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
fields_.Clear();
}
bool Struct::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Struct)
for (;;) {
@@ -383,6 +386,7 @@ void Struct::SerializeWithCachedSizes(
}
int Struct::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct)
int total_size = 0;
// map<string, .google.protobuf.Value> fields = 1;
@@ -405,29 +409,35 @@ int Struct::ByteSize() const {
}
void Struct::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Struct* source =
::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct)
MergeFrom(*source);
}
}
void Struct::MergeFrom(const Struct& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
fields_.MergeFrom(from.fields_);
}
void Struct::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Struct::CopyFrom(const Struct& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Struct)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -560,6 +570,7 @@ Value* Value::New(::google::protobuf::Arena* arena) const {
}
void Value::clear_kind() {
+// @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value)
switch(kind_case()) {
case kNullValue: {
// No need to clear
@@ -594,12 +605,13 @@ void Value::clear_kind() {
void Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Value)
clear_kind();
}
bool Value::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Value)
for (;;) {
@@ -811,6 +823,7 @@ void Value::SerializeWithCachedSizes(
}
int Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value)
int total_size = 0;
switch (kind_case()) {
@@ -862,18 +875,22 @@ int Value::ByteSize() const {
}
void Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Value>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value)
MergeFrom(*source);
}
}
void Value::MergeFrom(const Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
switch (from.kind_case()) {
case kNullValue: {
@@ -907,12 +924,14 @@ void Value::MergeFrom(const Value& from) {
}
void Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Value::CopyFrom(const Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Value)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1063,6 +1082,7 @@ void Value::clear_string_value() {
return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Value::release_string_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
if (has_string_value()) {
clear_has_kind();
return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -1141,6 +1161,7 @@ void Value::clear_struct_value() {
return kind_.struct_value_;
}
::google::protobuf::Struct* Value::release_struct_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value)
if (has_struct_value()) {
clear_has_kind();
::google::protobuf::Struct* temp = kind_.struct_value_;
@@ -1188,6 +1209,7 @@ void Value::clear_list_value() {
return kind_.list_value_;
}
::google::protobuf::ListValue* Value::release_list_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value)
if (has_list_value()) {
clear_has_kind();
::google::protobuf::ListValue* temp = kind_.list_value_;
@@ -1282,12 +1304,13 @@ ListValue* ListValue::New(::google::protobuf::Arena* arena) const {
}
void ListValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
values_.Clear();
}
bool ListValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.ListValue)
for (;;) {
@@ -1359,6 +1382,7 @@ void ListValue::SerializeWithCachedSizes(
}
int ListValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue)
int total_size = 0;
// repeated .google.protobuf.Value values = 1;
@@ -1376,29 +1400,35 @@ int ListValue::ByteSize() const {
}
void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const ListValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue)
MergeFrom(*source);
}
}
void ListValue::MergeFrom(const ListValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
values_.MergeFrom(from.values_);
}
void ListValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void ListValue::CopyFrom(const ListValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ListValue)
if (&from == this) return;
Clear();
MergeFrom(from);
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 0527c812..6a4764a7 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -550,6 +550,7 @@ inline ::std::string* Value::mutable_string_value() {
return kind_.string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Value::release_string_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
if (has_string_value()) {
clear_has_kind();
return kind_.string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -628,6 +629,7 @@ inline ::google::protobuf::Struct* Value::mutable_struct_value() {
return kind_.struct_value_;
}
inline ::google::protobuf::Struct* Value::release_struct_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value)
if (has_struct_value()) {
clear_has_kind();
::google::protobuf::Struct* temp = kind_.struct_value_;
@@ -675,6 +677,7 @@ inline ::google::protobuf::ListValue* Value::mutable_list_value() {
return kind_.list_value_;
}
inline ::google::protobuf::ListValue* Value::release_list_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value)
if (has_list_value()) {
clear_has_kind();
::google::protobuf::ListValue* temp = kind_.list_value_;
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index 8562e2c1..beeba811 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -33,6 +33,7 @@ syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
option java_package = "com.google.protobuf";
option java_outer_classname = "StructProto";
option java_multiple_files = true;
@@ -49,7 +50,7 @@ option objc_class_prefix = "GPB";
//
// The JSON representation for `Struct` is JSON object.
message Struct {
- // Map of dynamically typed values.
+ // Unordered map of dynamically typed values.
map<string, Value> fields = 1;
}
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 58334322..bbd8ee65 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -214,6 +214,8 @@ class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
hash_map(int a = 0, const HashFcn& b = HashFcn(),
const EqualKey& c = EqualKey(),
const Alloc& d = Alloc()) : BaseClass(b, d) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
template <typename Key,
@@ -222,6 +224,8 @@ template <typename Key,
class hash_set : public std::set<Key, HashFcn> {
public:
hash_set(int = 0) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
@@ -257,6 +261,8 @@ class hash_map
hash_map(int a = 0, const HashFcn& b = HashFcn(),
const EqualKey& c = EqualKey(),
const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
template <typename Key, typename HashFcn = hash<Key>,
@@ -266,6 +272,8 @@ class hash_set
Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
#else
@@ -315,6 +323,8 @@ class hash_map
hash_map(int a = 0, const HashFcn& b = HashFcn(),
const EqualKey& c = EqualKey(),
const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
template <typename Key, typename HashFcn = hash<Key>,
@@ -324,6 +334,8 @@ class hash_set
Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
+
+ HashFcn hash_function() const { return HashFcn(); }
};
#endif // !GOOGLE_PROTOBUF_MISSING_HASH
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
index d80c64f2..3a36b4b1 100644
--- a/src/google/protobuf/stubs/int128.cc
+++ b/src/google/protobuf/stubs/int128.cc
@@ -31,7 +31,7 @@
#include <google/protobuf/stubs/int128.h>
#include <iomanip>
-#include <iostream> // NOLINT(readability/streams)
+#include <ostream> // NOLINT(readability/streams)
#include <sstream>
namespace google {
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index 3108db8c..f69605d9 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -174,7 +174,7 @@ T* CheckNotNull(const char* /* file */, int /* line */,
#ifdef NDEBUG
-#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
+#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false)
#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
index 3a1ef8a8..27956a8e 100644
--- a/src/google/protobuf/stubs/mathutil.h
+++ b/src/google/protobuf/stubs/mathutil.h
@@ -83,7 +83,7 @@ class MathUtil {
if (value == T(0) || ::google::protobuf::internal::IsNan<T>(value)) {
return value;
}
- return value > T(0) ? value : -value;
+ return value > T(0) ? 1 : -1;
}
template<typename T>
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index ad848701..29f869ad 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -224,7 +224,7 @@ inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
template<typename T>
template<typename U>
inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
- : status_(other.status_), value_(other.status_.ok() ? other.value_ : NULL) {
+ : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
}
template<typename T>
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index ec3ffd5b..91671659 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -435,6 +435,44 @@ inline bool operator>=(StringPiece x, StringPiece y) {
// allow StringPiece to be logged
extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
+namespace internal {
+// StringPiece is not a POD and can not be used in an union (pre C++11). We
+// need a POD version of it.
+struct StringPiecePod {
+ // Create from a StringPiece.
+ static StringPiecePod CreateFromStringPiece(StringPiece str) {
+ StringPiecePod pod;
+ pod.data_ = str.data();
+ pod.size_ = str.size();
+ return pod;
+ }
+
+ // Cast to StringPiece.
+ operator StringPiece() const { return StringPiece(data_, size_); }
+
+ bool operator==(const char* value) const {
+ return StringPiece(data_, size_) == StringPiece(value);
+ }
+
+ char operator[](stringpiece_ssize_type i) const {
+ assert(0 <= i);
+ assert(i < size_);
+ return data_[i];
+ }
+
+ const char* data() const { return data_; }
+
+ stringpiece_ssize_type size() const {
+ return size_;
+ }
+
+ std::string ToString() const { return std::string(data_, size_); }
+ private:
+ const char* data_;
+ stringpiece_ssize_type size_;
+};
+
+} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
index 3272d8e3..83fdfe45 100644
--- a/src/google/protobuf/stubs/stringprintf.cc
+++ b/src/google/protobuf/stubs/stringprintf.cc
@@ -37,7 +37,6 @@
#include <stdio.h> // MSVC requires this for _vsnprintf
#include <vector>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/googletest.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 27d47575..8bdd6110 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -648,6 +648,9 @@ struct LIBPROTOBUF_EXPORT AlphaNum {
AlphaNum(StringPiece str)
: piece_data_(str.data()), piece_size_(str.size()) {}
+ AlphaNum(internal::StringPiecePod str)
+ : piece_data_(str.data()), piece_size_(str.size()) {}
+
size_t size() const { return piece_size_; }
const char *data() const { return piece_data_; }
@@ -847,6 +850,11 @@ LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
string* dest, bool do_padding);
+inline bool IsValidCodePoint(uint32 code_point) {
+ return code_point < 0xD800 ||
+ (code_point >= 0xE000 && code_point <= 0x10FFFF);
+}
+
static const int UTFmax = 4;
// ----------------------------------------------------------------------
// EncodeAsUTF8Char()
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index b0a5ce63..c0dfd53f 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -91,7 +91,10 @@ inline bool GetAnyFieldDescriptors(const Message& message,
string Message::DebugString() const {
string debug_string;
- TextFormat::PrintToString(*this, &debug_string);
+ TextFormat::Printer printer;
+ printer.SetExpandAny(true);
+
+ printer.PrintToString(*this, &debug_string);
return debug_string;
}
@@ -101,6 +104,7 @@ string Message::ShortDebugString() const {
TextFormat::Printer printer;
printer.SetSingleLineMode(true);
+ printer.SetExpandAny(true);
printer.PrintToString(*this, &debug_string);
// Single line mode currently might have an extra space at the end.
@@ -117,6 +121,7 @@ string Message::Utf8DebugString() const {
TextFormat::Printer printer;
printer.SetUseUtf8StringEscaping(true);
+ printer.SetExpandAny(true);
printer.PrintToString(*this, &debug_string);
@@ -1153,10 +1158,10 @@ class TextFormat::Printer::TextGenerator {
}
// Print text to the output stream.
- void Print(const char* text, int size) {
- int pos = 0; // The number of bytes we've written so far.
+ void Print(const char* text, size_t size) {
+ size_t pos = 0; // The number of bytes we've written so far.
- for (int i = 0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
if (text[i] == '\n') {
// Saw newline. If there is more text, we may need to insert an indent
// here. So, write what we have so far, including the '\n'.
@@ -1181,7 +1186,7 @@ class TextFormat::Printer::TextGenerator {
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
- void Write(const char* data, int size) {
+ void Write(const char* data, size_t size) {
if (failed_) return;
if (size == 0) return;
@@ -1780,14 +1785,12 @@ void TextFormat::Printer::PrintFieldValue(
? reflection->GetRepeatedStringReference(
message, field, index, &scratch)
: reflection->GetStringReference(message, field, &scratch);
- int64 size = value.size();
- if (truncate_string_field_longer_than_ > 0) {
- size = std::min(truncate_string_field_longer_than_,
- static_cast<int64>(value.size()));
- }
- string truncated_value(value.substr(0, size) + "...<truncated>...");
const string* value_to_print = &value;
- if (size < value.size()) {
+ string truncated_value;
+ if (truncate_string_field_longer_than_ > 0 &&
+ truncate_string_field_longer_than_ < value.size()) {
+ truncated_value = value.substr(0, truncate_string_field_longer_than_) +
+ "...<truncated>...";
value_to_print = &truncated_value;
}
if (field->type() == FieldDescriptor::TYPE_STRING) {
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 8d61be19..58aa3f8d 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -44,6 +44,8 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
@@ -52,10 +54,10 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/mathlimits.h>
namespace google {
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index c1c4402c..7cdf5093 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -83,9 +83,10 @@ void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() {
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\037google/protobuf/timestamp.proto\022\017googl"
"e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003"
- "\022\r\n\005nanos\030\002 \001(\005BT\n\023com.google.protobufB\016"
- "TimestampProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Pr"
- "otobuf.WellKnownTypesb\006proto3", 189);
+ "\022\r\n\005nanos\030\002 \001(\005B\201\001\n\023com.google.protobufB"
+ "\016TimestampProtoP\001Z+github.com/golang/pro"
+ "tobuf/ptypes/timestamp\240\001\001\370\001\001\242\002\003GPB\252\002\036Goo"
+ "gle.Protobuf.WellKnownTypesb\006proto3", 235);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/timestamp.proto", &protobuf_RegisterTypes);
Timestamp::default_instance_ = new Timestamp();
@@ -192,8 +193,17 @@ Timestamp* Timestamp::New(::google::protobuf::Arena* arena) const {
}
void Timestamp::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(Timestamp, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<Timestamp*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -209,7 +219,7 @@ void Timestamp::Clear() {
bool Timestamp::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Timestamp)
for (;;) {
@@ -301,6 +311,7 @@ void Timestamp::SerializeWithCachedSizes(
}
int Timestamp::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp)
int total_size = 0;
// optional int64 seconds = 1;
@@ -324,18 +335,22 @@ int Timestamp::ByteSize() const {
}
void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Timestamp* source =
::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp)
MergeFrom(*source);
}
}
void Timestamp::MergeFrom(const Timestamp& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.seconds() != 0) {
set_seconds(from.seconds());
@@ -346,12 +361,14 @@ void Timestamp::MergeFrom(const Timestamp& from) {
}
void Timestamp::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Timestamp::CopyFrom(const Timestamp& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Timestamp)
if (&from == this) return;
Clear();
MergeFrom(from);
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index b51fc3fa..7992a858 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -34,6 +34,7 @@ package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
option java_package = "com.google.protobuf";
option java_outer_classname = "TimestampProto";
option java_multiple_files = true;
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 7b47b3bd..759cab27 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -359,6 +359,7 @@ Type* Type::New(::google::protobuf::Arena* arena) const {
}
void Type::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
@@ -370,7 +371,7 @@ void Type::Clear() {
bool Type::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Type)
for (;;) {
@@ -603,6 +604,7 @@ void Type::SerializeWithCachedSizes(
}
int Type::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type)
int total_size = 0;
// optional string name = 1;
@@ -655,18 +657,22 @@ int Type::ByteSize() const {
}
void Type::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Type* source =
::google::protobuf::internal::DynamicCastToGenerated<const Type>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Type)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Type)
MergeFrom(*source);
}
}
void Type::MergeFrom(const Type& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
fields_.MergeFrom(from.fields_);
oneofs_.MergeFrom(from.oneofs_);
@@ -684,12 +690,14 @@ void Type::MergeFrom(const Type& from) {
}
void Type::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Type)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Type::CopyFrom(const Type& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Type)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -756,6 +764,7 @@ void Type::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Type::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Type.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -828,6 +837,7 @@ void Type::clear_oneofs() {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
}
::std::string* Type::add_oneofs() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs)
return oneofs_.Add();
}
void Type::add_oneofs(const ::std::string& value) {
@@ -904,6 +914,7 @@ const ::google::protobuf::SourceContext& Type::source_context() const {
return source_context_;
}
::google::protobuf::SourceContext* Type::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -1104,8 +1115,17 @@ Field* Field::New(::google::protobuf::Arena* arena) const {
}
void Field::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(Field, f) \
+ _Pragma("clang diagnostic pop")
+#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
&reinterpret_cast<Field*>(16)->f)
+#endif
#define ZR_(first, last) do {\
::memset(&first, 0,\
@@ -1128,7 +1148,7 @@ void Field::Clear() {
bool Field::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Field)
for (;;) {
@@ -1483,6 +1503,7 @@ void Field::SerializeWithCachedSizes(
}
int Field::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field)
int total_size = 0;
// optional .google.protobuf.Field.Kind kind = 1;
@@ -1559,18 +1580,22 @@ int Field::ByteSize() const {
}
void Field::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Field* source =
::google::protobuf::internal::DynamicCastToGenerated<const Field>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Field)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Field)
MergeFrom(*source);
}
}
void Field::MergeFrom(const Field& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
options_.MergeFrom(from.options_);
if (from.kind() != 0) {
@@ -1607,12 +1632,14 @@ void Field::MergeFrom(const Field& from) {
}
void Field::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Field)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Field::CopyFrom(const Field& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Field)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1725,6 +1752,7 @@ void Field::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Field::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1768,6 +1796,7 @@ void Field::clear_type_url() {
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Field::release_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url)
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1869,6 +1898,7 @@ void Field::clear_json_name() {
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Field::release_json_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name)
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1912,6 +1942,7 @@ void Field::clear_default_value() {
return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Field::release_default_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value)
return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2003,6 +2034,7 @@ Enum* Enum::New(::google::protobuf::Arena* arena) const {
}
void Enum::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
@@ -2013,7 +2045,7 @@ void Enum::Clear() {
bool Enum::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Enum)
for (;;) {
@@ -2206,6 +2238,7 @@ void Enum::SerializeWithCachedSizes(
}
int Enum::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum)
int total_size = 0;
// optional string name = 1;
@@ -2251,18 +2284,22 @@ int Enum::ByteSize() const {
}
void Enum::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Enum* source =
::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Enum)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Enum)
MergeFrom(*source);
}
}
void Enum::MergeFrom(const Enum& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
enumvalue_.MergeFrom(from.enumvalue_);
options_.MergeFrom(from.options_);
@@ -2279,12 +2316,14 @@ void Enum::MergeFrom(const Enum& from) {
}
void Enum::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Enum)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Enum::CopyFrom(const Enum& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Enum)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2350,6 +2389,7 @@ void Enum::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Enum::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Enum.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2444,6 +2484,7 @@ const ::google::protobuf::SourceContext& Enum::source_context() const {
return source_context_;
}
::google::protobuf::SourceContext* Enum::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -2547,6 +2588,7 @@ EnumValue* EnumValue::New(::google::protobuf::Arena* arena) const {
}
void EnumValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
number_ = 0;
options_.Clear();
@@ -2554,7 +2596,7 @@ void EnumValue::Clear() {
bool EnumValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.EnumValue)
for (;;) {
@@ -2689,6 +2731,7 @@ void EnumValue::SerializeWithCachedSizes(
}
int EnumValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue)
int total_size = 0;
// optional string name = 1;
@@ -2720,18 +2763,22 @@ int EnumValue::ByteSize() const {
}
void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const EnumValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValue)
MergeFrom(*source);
}
}
void EnumValue::MergeFrom(const EnumValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
options_.MergeFrom(from.options_);
if (from.name().size() > 0) {
@@ -2744,12 +2791,14 @@ void EnumValue::MergeFrom(const EnumValue& from) {
}
void EnumValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void EnumValue::CopyFrom(const EnumValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2813,6 +2862,7 @@ void EnumValue::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* EnumValue::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -2944,6 +2994,7 @@ Option* Option::New(::google::protobuf::Arena* arena) const {
}
void Option::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
value_ = NULL;
@@ -2951,7 +3002,7 @@ void Option::Clear() {
bool Option::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Option)
for (;;) {
@@ -3057,6 +3108,7 @@ void Option::SerializeWithCachedSizes(
}
int Option::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option)
int total_size = 0;
// optional string name = 1;
@@ -3080,18 +3132,22 @@ int Option::ByteSize() const {
}
void Option::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Option* source =
::google::protobuf::internal::DynamicCastToGenerated<const Option>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Option)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Option)
MergeFrom(*source);
}
}
void Option::MergeFrom(const Option& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.name().size() > 0) {
@@ -3103,12 +3159,14 @@ void Option::MergeFrom(const Option& from) {
}
void Option::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Option)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Option::CopyFrom(const Option& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Option)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -3171,6 +3229,7 @@ void Option::clear_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
::std::string* Option::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Option.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -3205,6 +3264,7 @@ const ::google::protobuf::Any& Option::value() const {
return value_;
}
::google::protobuf::Any* Option::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Option.value)
::google::protobuf::Any* temp = value_;
value_ = NULL;
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 76fe8a65..4255fa8c 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -328,25 +328,44 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef Field_Kind Kind;
- static const Kind TYPE_UNKNOWN = Field_Kind_TYPE_UNKNOWN;
- static const Kind TYPE_DOUBLE = Field_Kind_TYPE_DOUBLE;
- static const Kind TYPE_FLOAT = Field_Kind_TYPE_FLOAT;
- static const Kind TYPE_INT64 = Field_Kind_TYPE_INT64;
- static const Kind TYPE_UINT64 = Field_Kind_TYPE_UINT64;
- static const Kind TYPE_INT32 = Field_Kind_TYPE_INT32;
- static const Kind TYPE_FIXED64 = Field_Kind_TYPE_FIXED64;
- static const Kind TYPE_FIXED32 = Field_Kind_TYPE_FIXED32;
- static const Kind TYPE_BOOL = Field_Kind_TYPE_BOOL;
- static const Kind TYPE_STRING = Field_Kind_TYPE_STRING;
- static const Kind TYPE_GROUP = Field_Kind_TYPE_GROUP;
- static const Kind TYPE_MESSAGE = Field_Kind_TYPE_MESSAGE;
- static const Kind TYPE_BYTES = Field_Kind_TYPE_BYTES;
- static const Kind TYPE_UINT32 = Field_Kind_TYPE_UINT32;
- static const Kind TYPE_ENUM = Field_Kind_TYPE_ENUM;
- static const Kind TYPE_SFIXED32 = Field_Kind_TYPE_SFIXED32;
- static const Kind TYPE_SFIXED64 = Field_Kind_TYPE_SFIXED64;
- static const Kind TYPE_SINT32 = Field_Kind_TYPE_SINT32;
- static const Kind TYPE_SINT64 = Field_Kind_TYPE_SINT64;
+ static const Kind TYPE_UNKNOWN =
+ Field_Kind_TYPE_UNKNOWN;
+ static const Kind TYPE_DOUBLE =
+ Field_Kind_TYPE_DOUBLE;
+ static const Kind TYPE_FLOAT =
+ Field_Kind_TYPE_FLOAT;
+ static const Kind TYPE_INT64 =
+ Field_Kind_TYPE_INT64;
+ static const Kind TYPE_UINT64 =
+ Field_Kind_TYPE_UINT64;
+ static const Kind TYPE_INT32 =
+ Field_Kind_TYPE_INT32;
+ static const Kind TYPE_FIXED64 =
+ Field_Kind_TYPE_FIXED64;
+ static const Kind TYPE_FIXED32 =
+ Field_Kind_TYPE_FIXED32;
+ static const Kind TYPE_BOOL =
+ Field_Kind_TYPE_BOOL;
+ static const Kind TYPE_STRING =
+ Field_Kind_TYPE_STRING;
+ static const Kind TYPE_GROUP =
+ Field_Kind_TYPE_GROUP;
+ static const Kind TYPE_MESSAGE =
+ Field_Kind_TYPE_MESSAGE;
+ static const Kind TYPE_BYTES =
+ Field_Kind_TYPE_BYTES;
+ static const Kind TYPE_UINT32 =
+ Field_Kind_TYPE_UINT32;
+ static const Kind TYPE_ENUM =
+ Field_Kind_TYPE_ENUM;
+ static const Kind TYPE_SFIXED32 =
+ Field_Kind_TYPE_SFIXED32;
+ static const Kind TYPE_SFIXED64 =
+ Field_Kind_TYPE_SFIXED64;
+ static const Kind TYPE_SINT32 =
+ Field_Kind_TYPE_SINT32;
+ static const Kind TYPE_SINT64 =
+ Field_Kind_TYPE_SINT64;
static inline bool Kind_IsValid(int value) {
return Field_Kind_IsValid(value);
}
@@ -369,10 +388,14 @@ class LIBPROTOBUF_EXPORT Field : public ::google::protobuf::Message {
}
typedef Field_Cardinality Cardinality;
- static const Cardinality CARDINALITY_UNKNOWN = Field_Cardinality_CARDINALITY_UNKNOWN;
- static const Cardinality CARDINALITY_OPTIONAL = Field_Cardinality_CARDINALITY_OPTIONAL;
- static const Cardinality CARDINALITY_REQUIRED = Field_Cardinality_CARDINALITY_REQUIRED;
- static const Cardinality CARDINALITY_REPEATED = Field_Cardinality_CARDINALITY_REPEATED;
+ static const Cardinality CARDINALITY_UNKNOWN =
+ Field_Cardinality_CARDINALITY_UNKNOWN;
+ static const Cardinality CARDINALITY_OPTIONAL =
+ Field_Cardinality_CARDINALITY_OPTIONAL;
+ static const Cardinality CARDINALITY_REQUIRED =
+ Field_Cardinality_CARDINALITY_REQUIRED;
+ static const Cardinality CARDINALITY_REPEATED =
+ Field_Cardinality_CARDINALITY_REPEATED;
static inline bool Cardinality_IsValid(int value) {
return Field_Cardinality_IsValid(value);
}
@@ -865,6 +888,7 @@ inline ::std::string* Type::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Type::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Type.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -937,6 +961,7 @@ inline void Type::set_oneofs(int index, const char* value, size_t size) {
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
}
inline ::std::string* Type::add_oneofs() {
+ // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs)
return oneofs_.Add();
}
inline void Type::add_oneofs(const ::std::string& value) {
@@ -1013,6 +1038,7 @@ inline ::google::protobuf::SourceContext* Type::mutable_source_context() {
return source_context_;
}
inline ::google::protobuf::SourceContext* Type::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -1119,6 +1145,7 @@ inline ::std::string* Field::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Field::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1162,6 +1189,7 @@ inline ::std::string* Field::mutable_type_url() {
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Field::release_type_url() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url)
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1263,6 +1291,7 @@ inline ::std::string* Field::mutable_json_name() {
return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Field::release_json_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name)
return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1306,6 +1335,7 @@ inline ::std::string* Field::mutable_default_value() {
return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Field::release_default_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value)
return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1353,6 +1383,7 @@ inline ::std::string* Enum::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Enum::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Enum.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1447,6 +1478,7 @@ inline ::google::protobuf::SourceContext* Enum::mutable_source_context() {
return source_context_;
}
inline ::google::protobuf::SourceContext* Enum::release_source_context() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context)
::google::protobuf::SourceContext* temp = source_context_;
source_context_ = NULL;
@@ -1511,6 +1543,7 @@ inline ::std::string* EnumValue::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* EnumValue::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1602,6 +1635,7 @@ inline ::std::string* Option::mutable_name() {
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Option::release_name() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Option.name)
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
@@ -1636,6 +1670,7 @@ inline ::google::protobuf::Any* Option::mutable_value() {
return value_;
}
inline ::google::protobuf::Any* Option::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.Option.value)
::google::protobuf::Any* temp = value_;
value_ = NULL;
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 85fe6153..da56ae0a 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -696,6 +696,7 @@ message TestRequiredOneof {
}
}
+
// Test messages for packed fields
message TestPackedTypes {
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index 662c0e46..878ec7c1 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -43,8 +43,10 @@ option java_package = "com.google.protobuf";
// Same as TestAllTypes but with the lite runtime.
message TestAllTypesLite {
+
message NestedMessage {
optional int32 bb = 1;
+ optional int64 cc = 2;
}
enum NestedEnum {
@@ -159,6 +161,7 @@ message TestAllTypesLite {
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
+ NestedMessage oneof_lazy_nested_message = 115 [lazy = true];
}
}
@@ -383,3 +386,22 @@ message TestEmptyMessageLite{
message TestEmptyMessageWithExtensionsLite {
extensions 1 to max;
}
+
+enum V1EnumLite {
+ V1_FIRST = 1;
+}
+
+enum V2EnumLite {
+ V2_FIRST = 1;
+ V2_SECOND = 2;
+}
+
+message V1MessageLite {
+ required int32 int_field = 1;
+ optional V1EnumLite enum_field = 2 [ default = V1_FIRST ];
+}
+
+message V2MessageLite {
+ required int32 int_field = 1;
+ optional V2EnumLite enum_field = 2 [ default = V2_FIRST ];
+}
diff --git a/src/google/protobuf/unittest_proto3_arena_lite.proto b/src/google/protobuf/unittest_proto3_arena_lite.proto
new file mode 100644
index 00000000..5a60b90f
--- /dev/null
+++ b/src/google/protobuf/unittest_proto3_arena_lite.proto
@@ -0,0 +1,207 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+option optimize_for = LITE_RUNTIME;
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_arena_lite_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ ZERO = 0;
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ NEG = -1; // Intentionally negative.
+ }
+
+ // Singular
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ // Groups are not allowed in proto3.
+ // optional group OptionalGroup = 16 {
+ // optional int32 a = 17;
+ // }
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+ protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ NestedEnum optional_nested_enum = 21;
+ ForeignEnum optional_foreign_enum = 22;
+
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
+
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ // Groups are not allowed in proto3.
+ // repeated group RepeatedGroup = 46 {
+ // optional int32 a = 47;
+ // }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// Explicitly set packed to false
+message TestUnpackedTypes {
+ repeated int32 repeated_int32 = 1 [packed = false];
+ repeated int64 repeated_int64 = 2 [packed = false];
+ repeated uint32 repeated_uint32 = 3 [packed = false];
+ repeated uint64 repeated_uint64 = 4 [packed = false];
+ repeated sint32 repeated_sint32 = 5 [packed = false];
+ repeated sint64 repeated_sint64 = 6 [packed = false];
+ repeated fixed32 repeated_fixed32 = 7 [packed = false];
+ repeated fixed64 repeated_fixed64 = 8 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+ repeated float repeated_float = 11 [packed = false];
+ repeated double repeated_double = 12 [packed = false];
+ repeated bool repeated_bool = 13 [packed = false];
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+ NestedTestAllTypes child = 1;
+ TestAllTypes payload = 2;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_ZERO = 0;
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/google/protobuf/unittest_proto3_lite.proto b/src/google/protobuf/unittest_proto3_lite.proto
new file mode 100644
index 00000000..874ade6c
--- /dev/null
+++ b/src/google/protobuf/unittest_proto3_lite.proto
@@ -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.
+
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_lite_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ ZERO = 0;
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ NEG = -1; // Intentionally negative.
+ }
+
+ // Singular
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ // Groups are not allowed in proto3.
+ // optional group OptionalGroup = 16 {
+ // optional int32 a = 17;
+ // }
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+ protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ NestedEnum optional_nested_enum = 21;
+ ForeignEnum optional_foreign_enum = 22;
+
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
+
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ // Groups are not allowed in proto3.
+ // repeated group RepeatedGroup = 46 {
+ // optional int32 a = 47;
+ // }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+}
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// Explicitly set packed to false
+message TestUnpackedTypes {
+ repeated int32 repeated_int32 = 1 [packed = false];
+ repeated int64 repeated_int64 = 2 [packed = false];
+ repeated uint32 repeated_uint32 = 3 [packed = false];
+ repeated uint64 repeated_uint64 = 4 [packed = false];
+ repeated sint32 repeated_sint32 = 5 [packed = false];
+ repeated sint64 repeated_sint64 = 6 [packed = false];
+ repeated fixed32 repeated_fixed32 = 7 [packed = false];
+ repeated fixed64 repeated_fixed64 = 8 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+ repeated float repeated_float = 11 [packed = false];
+ repeated double repeated_double = 12 [packed = false];
+ repeated bool repeated_bool = 13 [packed = false];
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+ NestedTestAllTypes child = 1;
+ TestAllTypes payload = 2;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_ZERO = 0;
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
+
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 9f613265..60b8b8a5 100644
--- a/src/google/protobuf/util/field_comparator.cc
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -92,7 +92,27 @@ FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
case FieldDescriptor::CPPTYPE_INT64:
COMPARE_FIELD(Int64);
case FieldDescriptor::CPPTYPE_STRING:
- COMPARE_FIELD(String);
+ if (field->is_repeated()) {
+ // Allocate scratch strings to store the result if a conversion is
+ // needed.
+ string scratch1;
+ string scratch2;
+ return ResultFromBoolean(
+ CompareString(*field, reflection_1->GetRepeatedStringReference(
+ message_1, field, index_1, &scratch1),
+ reflection_2->GetRepeatedStringReference(
+ message_2, field, index_2, &scratch2)));
+ } else {
+ // Allocate scratch strings to store the result if a conversion is
+ // needed.
+ string scratch1;
+ string scratch2;
+ return ResultFromBoolean(CompareString(
+ *field,
+ reflection_1->GetStringReference(message_1, field, &scratch1),
+ reflection_2->GetStringReference(message_2, field, &scratch2)));
+ }
+ break;
case FieldDescriptor::CPPTYPE_UINT32:
COMPARE_FIELD(UInt32);
case FieldDescriptor::CPPTYPE_UINT64:
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 8b83c69f..1b4d65b0 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -91,9 +91,9 @@ class LIBPROTOBUF_EXPORT FieldComparator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
};
-// Basic implementation of FieldComparator. Supports four modes of floating
+// Basic implementation of FieldComparator. Supports three modes of floating
// point value comparison: exact, approximate using MathUtil::AlmostEqual
-// method, and arbitrarilly precise using MathUtil::WithinFractionOrMargin.
+// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
public:
enum FloatComparison {
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
index 23f7d51d..6fd631d8 100644
--- a/src/google/protobuf/util/field_comparator_test.cc
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -42,7 +42,6 @@
// and the opensource version gtest.h header includes cmath transitively
// somehow.
#include <gtest/gtest.h>
-
namespace google {
namespace protobuf {
namespace util {
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index c59f43aa..547c9fb5 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -52,6 +52,82 @@ void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
}
}
+bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) {
+ output->clear();
+ bool after_underscore = false;
+ for (int i = 0; i < input.size(); ++i) {
+ if (input[i] >= 'A' && input[i] <= 'Z') {
+ // The field name must not contain uppercase letters.
+ return false;
+ }
+ if (after_underscore) {
+ if (input[i] >= 'a' && input[i] <= 'z') {
+ output->push_back(input[i] + 'A' - 'a');
+ after_underscore = false;
+ } else {
+ // The character after a "_" must be a lowercase letter.
+ return false;
+ }
+ } else if (input[i] == '_') {
+ after_underscore = true;
+ } else {
+ output->push_back(input[i]);
+ }
+ }
+ if (after_underscore) {
+ // Trailing "_".
+ return false;
+ }
+ return true;
+}
+
+bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) {
+ output->clear();
+ for (int i = 0; i < input.size(); ++i) {
+ if (input[i] == '_') {
+ // The field name must not contain "_"s.
+ return false;
+ }
+ if (input[i] >= 'A' && input[i] <= 'Z') {
+ output->push_back('_');
+ output->push_back(input[i] + 'a' - 'A');
+ } else {
+ output->push_back(input[i]);
+ }
+ }
+ return true;
+}
+
+bool FieldMaskUtil::ToJsonString(const FieldMask& mask, string* out) {
+ out->clear();
+ for (int i = 0; i < mask.paths_size(); ++i) {
+ const string& path = mask.paths(i);
+ string camelcase_path;
+ if (!SnakeCaseToCamelCase(path, &camelcase_path)) {
+ return false;
+ }
+ if (i > 0) {
+ out->push_back(',');
+ }
+ out->append(camelcase_path);
+ }
+ return true;
+}
+
+bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
+ out->Clear();
+ vector<string> paths = Split(str, ",");
+ for (int i = 0; i < paths.size(); ++i) {
+ if (paths[i].empty()) continue;
+ string snakecase_path;
+ if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) {
+ return false;
+ }
+ out->add_paths(snakecase_path);
+ }
+ return true;
+}
+
bool FieldMaskUtil::InternalIsValidPath(const Descriptor* descriptor,
StringPiece path) {
vector<string> parts = Split(path, ".");
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index 92f69893..644161b9 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -45,11 +45,18 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
typedef google::protobuf::FieldMask FieldMask;
public:
- // Converts FieldMask to/from string, formatted according to proto3 JSON
- // spec for FieldMask (e.g., "foo,bar,baz.quz").
+ // Converts FieldMask to/from string, formatted by separating each path
+ // with a comma (e.g., "foo_bar,baz.quz").
static string ToString(const FieldMask& mask);
static void FromString(StringPiece str, FieldMask* out);
+ // Converts FieldMask to/from string, formatted according to proto3 JSON
+ // spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not
+ // style conforming (i.e., not snake_case when converted to string, or not
+ // camelCase when converted from string), the conversion will fail.
+ static bool ToJsonString(const FieldMask& mask, string* out);
+ static bool FromJsonString(StringPiece str, FieldMask* out);
+
// Checks whether the given path is valid for type T.
template <typename T>
static bool IsValidPath(StringPiece path) {
@@ -105,6 +112,35 @@ class LIBPROTOBUF_EXPORT FieldMaskUtil {
const MergeOptions& options, Message* destination);
private:
+ friend class SnakeCaseCamelCaseTest;
+ // Converts a field name from snake_case to camelCase:
+ // 1. Every character after "_" will be converted to uppercase.
+ // 2. All "_"s are removed.
+ // The conversion will fail if:
+ // 1. The field name contains uppercase letters.
+ // 2. Any character after a "_" is not a lowercase letter.
+ // If the conversion succeeds, it's guaranteed that the resulted
+ // camelCase name will yield the original snake_case name when
+ // converted using CamelCaseToSnakeCase().
+ //
+ // Note that the input can contain characters not allowed in C identifiers.
+ // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
+ // successfully.
+ static bool SnakeCaseToCamelCase(StringPiece input, string* output);
+ // Converts a field name from camelCase to snake_case:
+ // 1. Every uppercase letter is converted to lowercase with a additional
+ // preceding "-".
+ // The conversion will fail if:
+ // 1. The field name contains "_"s.
+ // If the conversion succeeds, it's guaranteed that the resulted
+ // snake_case name will yield the original camelCase name when
+ // converted using SnakeCaseToCamelCase().
+ //
+ // Note that the input can contain characters not allowed in C identifiers.
+ // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
+ // successfully.
+ static bool CamelCaseToSnakeCase(StringPiece input, string* output);
+
static bool InternalIsValidPath(const Descriptor* descriptor,
StringPiece path);
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index a9523250..9b7fb62a 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -30,6 +30,10 @@
#include <google/protobuf/util/field_mask_util.h>
+#include <algorithm>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/field_mask.pb.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
@@ -38,8 +42,77 @@
namespace google {
namespace protobuf {
namespace util {
+
+class SnakeCaseCamelCaseTest : public ::testing::Test {
+ protected:
+ string SnakeCaseToCamelCase(const string& input) {
+ string output;
+ if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
+ return output;
+ } else {
+ return "#FAIL#";
+ }
+ }
+
+ string CamelCaseToSnakeCase(const string& input) {
+ string output;
+ if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
+ return output;
+ } else {
+ return "#FAIL#";
+ }
+ }
+};
+
namespace {
+TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
+ EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
+ EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
+ EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
+ // No uppercase letter is allowed.
+ EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
+ // Any character after a "_" must be a lowercase letter.
+ // 1. "_" cannot be followed by another "_".
+ // 2. "_" cannot be followed by a digit.
+ // 3. "_" cannot appear as the last character.
+ EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
+ EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
+ EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
+ EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
+ EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
+ EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
+ // "_"s are not allowed.
+ EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
+}
+
+TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
+ // Enumerates all possible snake_case names and test that converting it to
+ // camelCase and then to snake_case again will yield the original name.
+ string name = "___abc123";
+ std::sort(name.begin(), name.end());
+ do {
+ string camelName = SnakeCaseToCamelCase(name);
+ if (camelName != "#FAIL#") {
+ EXPECT_EQ(name, CamelCaseToSnakeCase(camelName));
+ }
+ } while (std::next_permutation(name.begin(), name.end()));
+
+ // Enumerates all possible camelCase names and test that converting it to
+ // snake_case and then to camelCase again will yield the original name.
+ name = "abcABC123";
+ std::sort(name.begin(), name.end());
+ do {
+ string camelName = CamelCaseToSnakeCase(name);
+ if (camelName != "#FAIL#") {
+ EXPECT_EQ(name, SnakeCaseToCamelCase(camelName));
+ }
+ } while (std::next_permutation(name.begin(), name.end()));
+}
+
using protobuf_unittest::TestAllTypes;
using protobuf_unittest::NestedTestAllTypes;
using google::protobuf::FieldMask;
@@ -47,20 +120,43 @@ using google::protobuf::FieldMask;
TEST(FieldMaskUtilTest, StringFormat) {
FieldMask mask;
EXPECT_EQ("", FieldMaskUtil::ToString(mask));
- mask.add_paths("foo");
- EXPECT_EQ("foo", FieldMaskUtil::ToString(mask));
- mask.add_paths("bar");
- EXPECT_EQ("foo,bar", FieldMaskUtil::ToString(mask));
+ mask.add_paths("foo_bar");
+ EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
+ mask.add_paths("baz_quz");
+ EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
FieldMaskUtil::FromString("", &mask);
EXPECT_EQ(0, mask.paths_size());
- FieldMaskUtil::FromString("foo", &mask);
+ FieldMaskUtil::FromString("fooBar", &mask);
+ EXPECT_EQ(1, mask.paths_size());
+ EXPECT_EQ("fooBar", mask.paths(0));
+ FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
+ EXPECT_EQ(2, mask.paths_size());
+ EXPECT_EQ("fooBar", mask.paths(0));
+ EXPECT_EQ("bazQuz", mask.paths(1));
+}
+
+TEST(FieldMaskUtilTest, JsonStringFormat) {
+ FieldMask mask;
+ string value;
+ EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+ EXPECT_EQ("", value);
+ mask.add_paths("foo_bar");
+ EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+ EXPECT_EQ("fooBar", value);
+ mask.add_paths("bar_quz");
+ EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
+ EXPECT_EQ("fooBar,barQuz", value);
+
+ FieldMaskUtil::FromJsonString("", &mask);
+ EXPECT_EQ(0, mask.paths_size());
+ FieldMaskUtil::FromJsonString("fooBar", &mask);
EXPECT_EQ(1, mask.paths_size());
- EXPECT_EQ("foo", mask.paths(0));
- FieldMaskUtil::FromString("foo,bar", &mask);
+ EXPECT_EQ("foo_bar", mask.paths(0));
+ FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
EXPECT_EQ(2, mask.paths_size());
- EXPECT_EQ("foo", mask.paths(0));
- EXPECT_EQ("bar", mask.paths(1));
+ EXPECT_EQ("foo_bar", mask.paths(0));
+ EXPECT_EQ("baz_quz", mask.paths(1));
}
TEST(FieldMaskUtilTest, TestIsVaildPath) {
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
index 0cb8f6e1..e556888c 100644
--- a/src/google/protobuf/util/internal/constants.h
+++ b/src/google/protobuf/util/internal/constants.h
@@ -43,13 +43,23 @@ namespace converter {
const char kTypeServiceBaseUrl[] = "type.googleapis.com";
// Format string for RFC3339 timestamp formatting.
-const char kRfc3339TimeFormat[] = "%Y-%m-%dT%H:%M:%S";
+const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
-// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value.
-const int64 kMinSeconds = -315576000000;
+// Same as above, but the year value is not zero-padded i.e. this accepts
+// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
+const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
-// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value.
-const int64 kMaxSeconds = 315576000000;
+// Minimun seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMinSeconds = -62135596800;
+
+// Maximum seconds allowed in a google.protobuf.Timestamp value.
+const int64 kTimestampMaxSeconds = 253402300799;
+
+// Minimum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMinSeconds = -315576000000;
+
+// Maximum seconds allowed in a google.protobuf.Duration value.
+const int64 kDurationMaxSeconds = 315576000000;
// Nano seconds in a second.
const int32 kNanosPerSecond = 1000000000;
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index b557429f..72c0aca6 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -47,6 +47,7 @@ using google::protobuf::EnumDescriptor;
using google::protobuf::EnumValueDescriptor;
;
;
+;
using util::error::Code;
using util::Status;
using util::StatusOr;
@@ -248,11 +249,8 @@ StatusOr<string> DataPiece::ToBytes() const {
if (type_ == TYPE_BYTES) return str_.ToString();
if (type_ == TYPE_STRING) {
string decoded;
- if (!WebSafeBase64Unescape(str_, &decoded)) {
- if (!Base64Unescape(str_, &decoded)) {
- return InvalidArgument(
- ValueAsStringOrDefault("Invalid data in input."));
- }
+ if (!DecodeBase64(str_, &decoded)) {
+ return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
}
return decoded;
} else {
@@ -313,11 +311,49 @@ StatusOr<To> DataPiece::GenericConvert() const {
template <typename To>
StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const {
+ if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
+ return InvalidArgument(StrCat("\"", str_, "\""));
+ }
To result;
if (func(str_, &result)) return result;
return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
}
+bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
+ // Try web-safe decode first, if it fails, try the non-web-safe decode.
+ if (WebSafeBase64Unescape(src, dest)) {
+ if (use_strict_base64_decoding_) {
+ // In strict mode, check if the escaped version gives us the same value as
+ // unescaped.
+ string encoded;
+ // WebSafeBase64Escape does no padding by default.
+ WebSafeBase64Escape(*dest, &encoded);
+ // Remove trailing padding '=' characters before comparison.
+ StringPiece src_no_padding(src, 0, src.ends_with("=")
+ ? src.find_last_not_of('=') + 1
+ : src.length());
+ return encoded == src_no_padding;
+ }
+ return true;
+ }
+
+ if (Base64Unescape(src, dest)) {
+ if (use_strict_base64_decoding_) {
+ string encoded;
+ Base64Escape(
+ reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
+ &encoded, false);
+ StringPiece src_no_padding(src, 0, src.ends_with("=")
+ ? src.find_last_not_of('=') + 1
+ : src.length());
+ return encoded == src_no_padding;
+ }
+ return true;
+ }
+
+ return false;
+}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index f22bfe70..8b2e35d3 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -83,12 +83,15 @@ class LIBPROTOBUF_EXPORT DataPiece {
explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {}
explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {}
explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {}
- explicit DataPiece(StringPiece value)
+ DataPiece(StringPiece value, bool use_strict_base64_decoding)
: type_(TYPE_STRING),
- str_(StringPiecePod::CreateFromStringPiece(value)) {}
+ str_(StringPiecePod::CreateFromStringPiece(value)),
+ use_strict_base64_decoding_(use_strict_base64_decoding) {}
// Constructor for bytes. The second parameter is not used.
- explicit DataPiece(StringPiece value, bool dummy)
- : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {}
+ DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding)
+ : type_(TYPE_BYTES),
+ str_(StringPiecePod::CreateFromStringPiece(value)),
+ use_strict_base64_decoding_(use_strict_base64_decoding) {}
DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {}
DataPiece& operator=(const DataPiece& x) {
type_ = x.type_;
@@ -165,32 +168,13 @@ class LIBPROTOBUF_EXPORT DataPiece {
template <typename To>
util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const;
+ // Decodes a base64 string. Returns true on success.
+ bool DecodeBase64(StringPiece src, string* dest) const;
+
// Data type for this piece of data.
Type type_;
- // StringPiece is not a POD and can not be used in an union (pre C++11). We
- // need a POD version of it.
- struct StringPiecePod {
- const char* data;
- int size;
-
- // Create from a StringPiece.
- static StringPiecePod CreateFromStringPiece(StringPiece str) {
- StringPiecePod pod;
- pod.data = str.data();
- pod.size = str.size();
- return pod;
- }
-
- // Cast to StringPiece.
- operator StringPiece() const { return StringPiece(data, size); }
-
- bool operator==(const char* value) const {
- return StringPiece(data, size) == StringPiece(value);
- }
-
- string ToString() const { return string(data, size); }
- };
+ typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
// Stored piece of data.
union {
@@ -203,6 +187,9 @@ class LIBPROTOBUF_EXPORT DataPiece {
bool bool_;
StringPiecePod str_;
};
+
+ // Uses a stricter version of base64 decoding for byte fields.
+ bool use_strict_base64_decoding_;
};
} // namespace converter
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index a63e560d..21d7a2e4 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -51,7 +51,7 @@ template <typename T>
T ConvertTo(StringPiece value, StatusOr<T> (DataPiece::*converter_fn)() const,
T default_value) {
if (value.empty()) return default_value;
- StatusOr<T> result = (DataPiece(value).*converter_fn)();
+ StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
return result.ok() ? result.ValueOrDie() : default_value;
}
} // namespace
@@ -64,6 +64,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
type_(type),
current_(NULL),
root_(NULL),
+ field_scrub_callback_(NULL),
ow_(ow) {}
DefaultValueObjectWriter::~DefaultValueObjectWriter() {
@@ -153,7 +154,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
// Since StringPiece is essentially a pointer, takes a copy of "value" to
// avoid ownership issues.
string_values_.push_back(new string(value.ToString()));
- RenderDataPiece(name, DataPiece(*string_values_.back()));
+ RenderDataPiece(name, DataPiece(*string_values_.back(), true));
}
return this;
}
@@ -163,7 +164,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
if (current_ == NULL) {
ow_->RenderBytes(name, value);
} else {
- RenderDataPiece(name, DataPiece(value));
+ RenderDataPiece(name, DataPiece(value, false, true));
}
return this;
}
@@ -178,16 +179,25 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
return this;
}
+void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
+ FieldScrubCallBackPtr field_scrub_callback) {
+ field_scrub_callback_.reset(field_scrub_callback.release());
+}
+
DefaultValueObjectWriter::Node::Node(const string& name,
const google::protobuf::Type* type,
NodeKind kind, const DataPiece& data,
- bool is_placeholder)
+ bool is_placeholder,
+ const vector<string>& path,
+ FieldScrubCallBack* field_scrub_callback)
: name_(name),
type_(type),
kind_(kind),
is_any_(false),
data_(data),
- is_placeholder_(is_placeholder) {}
+ is_placeholder_(is_placeholder),
+ path_(path),
+ field_scrub_callback_(field_scrub_callback) {}
DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
StringPiece name) {
@@ -291,6 +301,19 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
for (int i = 0; i < type_->fields_size(); ++i) {
const google::protobuf::Field& field = type_->fields(i);
+
+ // This code is checking if the field to be added to the tree should be
+ // scrubbed or not by calling the field_scrub_callback_ callback function.
+ vector<string> path;
+ if (!path_.empty()) {
+ path.insert(path.begin(), path_.begin(), path_.end());
+ }
+ path.push_back(field.name());
+ if (field_scrub_callback_ != NULL &&
+ field_scrub_callback_->Run(path, &field)) {
+ continue;
+ }
+
hash_map<string, int>::iterator found =
orig_children_map.find(field.name());
// If the child field has already been set, we just add it to the new list
@@ -343,7 +366,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren(
field.json_name(), field_type, kind,
kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo)
: DataPiece::NullData(),
- true));
+ true, path, field_scrub_callback_));
new_children.push_back(child.release());
}
// Adds all leftover nodes in children_ to the beginning of new_child.
@@ -368,7 +391,8 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
DataPiece DefaultValueObjectWriter::FindEnumDefault(
const google::protobuf::Field& field, const TypeInfo* typeinfo) {
- if (!field.default_value().empty()) return DataPiece(field.default_value());
+ if (!field.default_value().empty())
+ return DataPiece(field.default_value(), true);
const google::protobuf::Enum* enum_type =
typeinfo->GetEnumByTypeUrl(field.type_url());
@@ -379,7 +403,7 @@ DataPiece DefaultValueObjectWriter::FindEnumDefault(
}
// We treat the first value as the default if none is specified.
return enum_type->enumvalue_size() > 0
- ? DataPiece(enum_type->enumvalue(0).name())
+ ? DataPiece(enum_type->enumvalue(0).name(), true)
: DataPiece::NullData();
}
@@ -416,10 +440,10 @@ DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false));
}
case google::protobuf::Field_Kind_TYPE_STRING: {
- return DataPiece(field.default_value());
+ return DataPiece(field.default_value(), true);
}
case google::protobuf::Field_Kind_TYPE_BYTES: {
- return DataPiece(field.default_value(), false);
+ return DataPiece(field.default_value(), false, true);
}
case google::protobuf::Field_Kind_TYPE_UINT32:
case google::protobuf::Field_Kind_TYPE_FIXED32: {
@@ -436,8 +460,9 @@ DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
StringPiece name) {
if (current_ == NULL) {
+ vector<string> path;
root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
- false));
+ false, path, field_scrub_callback_.get()));
root_->PopulateChildren(typeinfo_);
current_ = root_.get();
return this;
@@ -451,7 +476,9 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP)
? current_->type()
: NULL),
- OBJECT, DataPiece::NullData(), false));
+ OBJECT, DataPiece::NullData(), false,
+ child == NULL ? current_->path() : child->path(),
+ field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
}
@@ -480,8 +507,9 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
StringPiece name) {
if (current_ == NULL) {
- root_.reset(
- new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false));
+ vector<string> path;
+ root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(),
+ false, path, field_scrub_callback_.get()));
current_ = root_.get();
return this;
}
@@ -489,7 +517,9 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
Node* child = current_->FindChild(name);
if (child == NULL || child->kind() != LIST) {
google::protobuf::scoped_ptr<Node> node(
- new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false));
+ new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false,
+ child == NULL ? current_->path() : child->path(),
+ field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
}
@@ -545,7 +575,9 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
if (child == NULL || child->kind() != PRIMITIVE) {
// No children are found, creates a new child.
google::protobuf::scoped_ptr<Node> node(
- new Node(name.ToString(), NULL, PRIMITIVE, data, false));
+ new Node(name.ToString(), NULL, PRIMITIVE, data, false,
+ child == NULL ? current_->path() : child->path(),
+ field_scrub_callback_.get()));
child = node.get();
current_->AddChild(node.release());
} else {
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 695b9dd8..1d85bed8 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -38,6 +38,7 @@
#include <stack>
#include <vector>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/datapiece.h>
@@ -59,6 +60,25 @@ namespace converter {
// with their default values (0 for numbers, "" for strings, etc).
class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
public:
+ // A Callback function to check whether a field needs to be scrubbed.
+ //
+ // Returns true if the field should not be present in the output. Returns
+ // false otherwise.
+ //
+ // The 'path' parameter is a vector of path to the field from root. For
+ // example: if a nested field "a.b.c" (b is the parent message field of c and
+ // a is the parent message field of b), then the vector should contain { "a",
+ // "b", "c" }.
+ //
+ // The Field* should point to the google::protobuf::Field of "c".
+ typedef ResultCallback2<bool /*return*/,
+ const std::vector<string>& /*path of the field*/,
+ const google::protobuf::Field* /*field*/>
+ FieldScrubCallBack;
+
+ // A unique pointer to a DefaultValueObjectWriter::FieldScrubCallBack.
+ typedef google::protobuf::scoped_ptr<FieldScrubCallBack> FieldScrubCallBackPtr;
+
DefaultValueObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
ObjectWriter* ow);
@@ -98,6 +118,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
virtual DefaultValueObjectWriter* RenderNull(StringPiece name);
+ // Register the callback for scrubbing of fields. Owership of
+ // field_scrub_callback pointer is also transferred to this class
+ void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback);
+
private:
enum NodeKind {
PRIMITIVE = 0,
@@ -111,7 +135,8 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
class LIBPROTOBUF_EXPORT Node {
public:
Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
- const DataPiece& data, bool is_placeholder);
+ const DataPiece& data, bool is_placeholder, const vector<string>& path,
+ FieldScrubCallBack* field_scrub_callback);
virtual ~Node() {
for (int i = 0; i < children_.size(); ++i) {
delete children_[i];
@@ -137,17 +162,19 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Accessors
const string& name() const { return name_; }
- const google::protobuf::Type* type() { return type_; }
+ const vector<string>& path() const { return path_; }
+
+ const google::protobuf::Type* type() const { return type_; }
void set_type(const google::protobuf::Type* type) { type_ = type; }
- NodeKind kind() { return kind_; }
+ NodeKind kind() const { return kind_; }
- int number_of_children() { return children_.size(); }
+ int number_of_children() const { return children_.size(); }
void set_data(const DataPiece& data) { data_ = data; }
- bool is_any() { return is_any_; }
+ bool is_any() const { return is_any_; }
void set_is_any(bool is_any) { is_any_ = is_any; }
@@ -181,6 +208,15 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// the parent node's StartObject()/StartList() method is called with this
// node's name.
bool is_placeholder_;
+
+ // Path of the field of this node
+ std::vector<string> path_;
+
+ // Pointer to function for determining whether a field needs to be scrubbed
+ // or not. This callback is owned by the creator of this node.
+ FieldScrubCallBack* field_scrub_callback_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
};
// Populates children of "node" if it is an "any" Node and its real type has
@@ -221,6 +257,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// The stack to hold the path of Nodes from current_ to root_;
std::stack<Node*> stack_;
+ // Unique Pointer to function for determining whether a field needs to be
+ // scrubbed or not.
+ FieldScrubCallBackPtr field_scrub_callback_;
+
ObjectWriter* ow_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 94d2ab7a..b84210c1 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -46,6 +46,7 @@ namespace util {
namespace converter {
using strings::ArrayByteSource;
+;
JsonObjectWriter::~JsonObjectWriter() {
if (!element_->is_root()) {
@@ -81,13 +82,11 @@ JsonObjectWriter* JsonObjectWriter::EndList() {
return this;
}
-JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name,
- bool value) {
+JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, bool value) {
return RenderSimple(name, value ? "true" : "false");
}
-JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
- int32 value) {
+JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, int32 value) {
return RenderSimple(name, SimpleItoa(value));
}
@@ -96,8 +95,7 @@ JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
return RenderSimple(name, SimpleItoa(value));
}
-JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
- int64 value) {
+JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, int64 value) {
WritePrefix(name);
WriteChar('"');
stream_->WriteString(SimpleItoa(value));
@@ -124,8 +122,7 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
return RenderString(name, DoubleAsString(value));
}
-JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
- float value) {
+JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) {
if (MathLimits<float>::IsFinite(value)) {
return RenderSimple(name, SimpleFtoa(value));
}
@@ -148,7 +145,12 @@ JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
StringPiece value) {
WritePrefix(name);
string base64;
- Base64Escape(value, &base64);
+
+ if (use_websafe_base64_for_bytes_)
+ WebSafeBase64Escape(value.ToString(), &base64);
+ else
+ Base64Escape(value, &base64);
+
WriteChar('"');
// TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
// directly to the stream, rather than first putting them
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index 761a0a10..cb7e2fb3 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -90,9 +90,10 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
JsonObjectWriter(StringPiece indent_string,
google::protobuf::io::CodedOutputStream* out)
: element_(new Element(NULL)),
- stream_(out), sink_(out),
- indent_string_(indent_string.ToString()) {
- }
+ stream_(out),
+ sink_(out),
+ indent_string_(indent_string.ToString()),
+ use_websafe_base64_for_bytes_(false) {}
virtual ~JsonObjectWriter();
// ObjectWriter methods.
@@ -111,6 +112,10 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value);
virtual JsonObjectWriter* RenderNull(StringPiece name);
+ void set_use_websafe_base64_for_bytes(bool value) {
+ use_websafe_base64_for_bytes_ = value;
+ }
+
protected:
class LIBPROTOBUF_EXPORT Element : public BaseElement {
public:
@@ -195,6 +200,10 @@ class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
ByteSinkWrapper sink_;
const string indent_string_;
+ // Whether to use regular or websafe base64 encoding for byte fields. Defaults
+ // to regular base64 encoding.
+ bool use_websafe_base64_for_bytes_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter);
};
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index 9d820162..b87b06ac 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -58,7 +58,7 @@ class JsonObjectWriterTest : public ::testing::Test {
string output_;
StringOutputStream* const str_stream_;
CodedOutputStream* const out_stream_;
- ObjectWriter* ow_;
+ JsonObjectWriter* ow_;
};
TEST_F(JsonObjectWriterTest, EmptyRootObject) {
@@ -283,6 +283,30 @@ TEST_F(JsonObjectWriterTest, Stringification) {
output_.substr(0, out_stream_->ByteCount()));
}
+TEST_F(JsonObjectWriterTest, TestRegularByteEncoding) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->StartObject("")
+ ->RenderBytes("bytes", "\x03\xef\xc0")
+ ->EndObject();
+
+ // Test that we get regular (non websafe) base64 encoding on byte fields by
+ // default.
+ EXPECT_EQ("{\"bytes\":\"A+/A\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
+TEST_F(JsonObjectWriterTest, TestWebsafeByteEncoding) {
+ ow_ = new JsonObjectWriter("", out_stream_);
+ ow_->set_use_websafe_base64_for_bytes(true);
+ ow_->StartObject("")
+ ->RenderBytes("bytes", "\x03\xef\xc0")
+ ->EndObject();
+
+ // Test that we get websafe base64 encoding when explicitly asked.
+ EXPECT_EQ("{\"bytes\":\"A-_A\"}",
+ output_.substr(0, out_stream_->ByteCount()));
+}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index df916751..39be7b03 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -42,8 +42,9 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/object_writer.h>
+#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
@@ -59,7 +60,7 @@ using util::error::INVALID_ARGUMENT;
namespace converter {
-// Number of digits in a unicode escape sequence (/uXXXX)
+// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
static const int kUnicodeEscapedLength = 6;
// Length of the true, false, and null literals.
@@ -419,9 +420,45 @@ util::Status JsonStreamParser::ParseUnicodeEscape() {
}
code = (code << 4) + hex_digit_to_int(p_.data()[i]);
}
+ if (code >= JsonEscaping::kMinHighSurrogate &&
+ code <= JsonEscaping::kMaxHighSurrogate) {
+ if (p_.length() < 2 * kUnicodeEscapedLength) {
+ if (!finishing_) {
+ return util::Status::CANCELLED;
+ }
+ if (!coerce_to_utf8_) {
+ return ReportFailure("Missing low surrogate.");
+ }
+ } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
+ p_.data()[kUnicodeEscapedLength + 1] == 'u') {
+ uint32 low_code = 0;
+ for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
+ ++i) {
+ if (!isxdigit(p_.data()[i])) {
+ return ReportFailure("Invalid escape sequence.");
+ }
+ low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
+ }
+ if (low_code >= JsonEscaping::kMinLowSurrogate &&
+ low_code <= JsonEscaping::kMaxLowSurrogate) {
+ // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint.
+ code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) +
+ JsonEscaping::kMinSupplementaryCodePoint;
+ // Advance past the first code unit escape.
+ p_.remove_prefix(kUnicodeEscapedLength);
+ } else if (!coerce_to_utf8_) {
+ return ReportFailure("Invalid low surrogate.");
+ }
+ } else if (!coerce_to_utf8_) {
+ return ReportFailure("Missing low surrogate.");
+ }
+ }
+ if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
+ return ReportFailure("Invalid unicode code point.");
+ }
char buf[UTFmax];
int len = EncodeAsUTF8Char(code, buf);
- // Advance past the unicode escape.
+ // Advance past the [final] code unit escape.
p_.remove_prefix(kUnicodeEscapedLength);
parsed_storage_.append(buf, len);
return util::Status::OK;
@@ -473,7 +510,7 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
floating = true;
continue;
}
- if (c == '+' || c == '-') continue;
+ if (c == '+' || c == '-' || c == 'x') continue;
// Not a valid number character, break out.
break;
}
@@ -499,6 +536,10 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
// Positive non-floating point number, parse as a uint64.
if (!negative) {
+ // Octal/Hex numbers are not valid JSON values.
+ if (number.length() >= 2 && number[0] == '0') {
+ return ReportFailure("Octal/hex numbers are not valid JSON values.");
+ }
if (!safe_strtou64(number, &result->uint_val)) {
return ReportFailure("Unable to parse number.");
}
@@ -507,6 +548,10 @@ util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
return util::Status::OK;
}
+ // Octal/Hex numbers are not valid JSON values.
+ if (number.length() >= 3 && number[1] == '0') {
+ return ReportFailure("Octal/hex numbers are not valid JSON values.");
+ }
// Negative non-floating point number, parse as an int64.
if (!safe_strto64(number, &result->int_val)) {
return ReportFailure("Unable to parse number.");
@@ -677,8 +722,9 @@ util::Status JsonStreamParser::ReportFailure(StringPiece message) {
static const int kContextLength = 20;
const char* p_start = p_.data();
const char* json_start = json_.data();
- const char* begin = max(p_start - kContextLength, json_start);
- const char* end = min(p_start + kContextLength, json_start + json_.size());
+ const char* begin = std::max(p_start - kContextLength, json_start);
+ const char* end =
+ std::min(p_start + kContextLength, json_start + json_.size());
StringPiece segment(begin, end - begin);
string location(p_start - begin, ' ');
location.push_back('^');
@@ -706,8 +752,8 @@ void JsonStreamParser::SkipWhitespace() {
void JsonStreamParser::Advance() {
// Advance by moving one UTF8 character while making sure we don't go beyond
// the length of StringPiece.
- p_.remove_prefix(
- min<int>(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
+ p_.remove_prefix(std::min<int>(
+ p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
}
util::Status JsonStreamParser::ParseKey() {
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index 3414826e..059ea6d8 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -124,8 +124,9 @@ class JsonStreamParserTest : public ::testing::Test {
EXPECT_OK(result);
}
- void DoErrorTest(StringPiece json, int split, StringPiece error_prefix) {
- util::Status result = RunTest(json, split);
+ void DoErrorTest(StringPiece json, int split, StringPiece error_prefix,
+ bool coerce_utf8 = false) {
+ util::Status result = RunTest(json, split, coerce_utf8);
EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
StringPiece error_message(result.error_message());
EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
@@ -230,6 +231,32 @@ TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
}
}
+TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
+ StringPiece str = "01234";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+ }
+ str = "-01234";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
+ StringPiece str = "0x1234";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+ }
+ str = "-0x1234";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+ }
+ str = "12x34";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Unable to parse number.");
+ }
+}
+
// - single and double quoted strings
TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
StringPiece str = "\"\"";
@@ -351,19 +378,62 @@ TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
}
-#ifndef _MSC_VER
// - unicode handling in strings
TEST_F(JsonStreamParserTest, UnicodeEscaping) {
StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
for (int i = 0; i <= str.length(); ++i) {
- // TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
- // In protobuf we use UTF-8 for strings, but for JSON we probably should
- // allow different encodings?
- ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
+ ow_.StartList("")
+ ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
+ ->EndList();
+ DoTest(str, i);
+ }
+}
+
+// - unicode UTF-16 surrogate pair handling in strings
+TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
+ StringPiece str =
+ "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\\uD83C\\uDF6F\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ ow_.StartList("")
+ ->RenderString("",
+ "\xE0\xAF\xAE\xF0\x90\x87\xB1\xF0\x93\x86\xA4\xF0"
+ "\x9F\x90\x9D\xF0\x9F\x8D\xAF")
+ ->EndList();
DoTest(str, i);
}
}
-#endif
+
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
+ // A low surrogate alone.
+ StringPiece str = "[\"\\ude36\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid unicode code point.");
+ }
+}
+
+TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
+ // A high surrogate alone.
+ StringPiece str = "[\"\\ud83d\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Missing low surrogate.");
+ }
+ // A high surrogate with some trailing characters.
+ str = "[\"\\ud83d|ude36\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Missing low surrogate.");
+ }
+ // A high surrogate with half a low surrogate.
+ str = "[\"\\ud83d\\ude--\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid escape sequence.");
+ }
+ // Two high surrogates.
+ str = "[\"\\ud83d\\ud83d\"]";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid low surrogate.");
+ }
+}
// - ascii escaping (\b, \f, \n, \r, \t, \v)
TEST_F(JsonStreamParserTest, AsciiEscaping) {
@@ -629,6 +699,22 @@ TEST_F(JsonStreamParserTest, DoubleTooBig) {
}
*/
+// invalid bare backslash.
+TEST_F(JsonStreamParserTest, UnfinishedEscape) {
+ StringPiece str = "\"\\";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Closing quote expected in string.");
+ }
+}
+
+// invalid bare backslash u.
+TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
+ StringPiece str = "\"\\u";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Illegal hex string.");
+ }
+}
+
// invalid unicode sequence.
TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
StringPiece str = "\"\\u12";
@@ -637,6 +723,15 @@ TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
}
}
+// invalid unicode sequence (valid in modern EcmaScript but not in JSON).
+TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
+ StringPiece str = "\"\\u{1f36f}\"";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid escape sequence.");
+ }
+}
+
+
TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
StringPiece str = "\"\\u12$4hello";
for (int i = 0; i <= str.length(); ++i) {
@@ -644,6 +739,14 @@ TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
}
}
+// invalid unicode sequence in low half surrogate: g is not a hex digit.
+TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
+ StringPiece str = "\"\\ud800\\udcfg\"";
+ for (int i = 0; i <= str.length(); ++i) {
+ DoErrorTest(str, i, "Invalid escape sequence.");
+ }
+}
+
// Extra commas with an object or array.
TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
StringPiece str = "{'k1': true,,'k2': false}";
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
index e695f45e..9f07363d 100644
--- a/src/google/protobuf/util/internal/object_writer.h
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -105,10 +105,27 @@ class LIBPROTOBUF_EXPORT ObjectWriter {
static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
ObjectWriter* ow);
+ // Indicates whether this ObjectWriter has completed writing the root message,
+ // usually this means writing of one complete object. Subclasses must override
+ // this behavior appropriately.
+ virtual bool done() { return false; }
+
+ void set_use_strict_base64_decoding(bool value) {
+ use_strict_base64_decoding_ = value;
+ }
+
+ bool use_strict_base64_decoding() const {
+ return use_strict_base64_decoding_;
+ }
+
protected:
- ObjectWriter() {}
+ ObjectWriter() : use_strict_base64_decoding_(true) {}
private:
+ // If set to true, we use the stricter version of base64 decoding for byte
+ // fields by making sure decoded version encodes back to the original string.
+ bool use_strict_base64_decoding_;
+
// Do not add any data members to this class.
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter);
};
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 47e0009e..36b79410 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -447,9 +447,7 @@ ProtoWriter* ProtoWriter::StartObject(StringPiece name) {
return this;
}
- WriteTag(*field);
- element_.reset(new ProtoElement(element_.release(), field, *type, false));
- return this;
+ return StartObjectField(*field, *type);
}
ProtoWriter* ProtoWriter::EndObject() {
@@ -488,8 +486,7 @@ ProtoWriter* ProtoWriter::StartList(StringPiece name) {
return this;
}
- element_.reset(new ProtoElement(element_.release(), field, *type, true));
- return this;
+ return StartListField(*field, *type);
}
ProtoWriter* ProtoWriter::EndList() {
@@ -518,84 +515,128 @@ ProtoWriter* ProtoWriter::RenderDataPiece(StringPiece name,
return this;
}
+ return RenderPrimitiveField(*field, *type, data);
+}
+
+bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
+ StringPiece unnormalized_name) {
+ if (element_ == NULL) return true;
+
+ if (field.oneof_index() > 0) {
+ if (element_->IsOneofIndexTaken(field.oneof_index())) {
+ InvalidValue(
+ "oneof",
+ StrCat("oneof field '",
+ element_->type().oneofs(field.oneof_index() - 1),
+ "' is already set. Cannot set '", unnormalized_name, "'"));
+ return false;
+ }
+ element_->TakeOneofIndex(field.oneof_index());
+ }
+ return true;
+}
+
+bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) {
+ return field.cardinality() ==
+ google::protobuf::Field_Cardinality_CARDINALITY_REPEATED;
+}
+
+ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field,
+ const google::protobuf::Type& type) {
+ WriteTag(field);
+ element_.reset(new ProtoElement(element_.release(), &field, type, false));
+ return this;
+}
+
+ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field,
+ const google::protobuf::Type& type) {
+ element_.reset(new ProtoElement(element_.release(), &field, type, true));
+ return this;
+}
+
+ProtoWriter* ProtoWriter::RenderPrimitiveField(
+ const google::protobuf::Field& field, const google::protobuf::Type& type,
+ const DataPiece& data) {
+ Status status;
+
// Pushing a ProtoElement and then pop it off at the end for 2 purposes:
// error location reporting and required field accounting.
- element_.reset(new ProtoElement(element_.release(), field, *type, false));
+ element_.reset(new ProtoElement(element_.release(), &field, type, false));
- if (field->kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
- field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
- InvalidValue(field->type_url().empty()
- ? google::protobuf::Field_Kind_Name(field->kind())
- : field->type_url(),
+ if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN ||
+ field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
+ InvalidValue(field.type_url().empty()
+ ? google::protobuf::Field_Kind_Name(field.kind())
+ : field.type_url(),
data.ValueAsStringOrDefault(""));
element_.reset(element()->pop());
return this;
}
- switch (field->kind()) {
+ switch (field.kind()) {
case google::protobuf::Field_Kind_TYPE_INT32: {
- status = WriteInt32(field->number(), data, stream_.get());
+ status = WriteInt32(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_SFIXED32: {
- status = WriteSFixed32(field->number(), data, stream_.get());
+ status = WriteSFixed32(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_SINT32: {
- status = WriteSInt32(field->number(), data, stream_.get());
+ status = WriteSInt32(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_FIXED32: {
- status = WriteFixed32(field->number(), data, stream_.get());
+ status = WriteFixed32(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_UINT32: {
- status = WriteUInt32(field->number(), data, stream_.get());
+ status = WriteUInt32(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_INT64: {
- status = WriteInt64(field->number(), data, stream_.get());
+ status = WriteInt64(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_SFIXED64: {
- status = WriteSFixed64(field->number(), data, stream_.get());
+ status = WriteSFixed64(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_SINT64: {
- status = WriteSInt64(field->number(), data, stream_.get());
+ status = WriteSInt64(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_FIXED64: {
- status = WriteFixed64(field->number(), data, stream_.get());
+ status = WriteFixed64(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_UINT64: {
- status = WriteUInt64(field->number(), data, stream_.get());
+ status = WriteUInt64(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_DOUBLE: {
- status = WriteDouble(field->number(), data, stream_.get());
+ status = WriteDouble(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_FLOAT: {
- status = WriteFloat(field->number(), data, stream_.get());
+ status = WriteFloat(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_BOOL: {
- status = WriteBool(field->number(), data, stream_.get());
+ status = WriteBool(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_BYTES: {
- status = WriteBytes(field->number(), data, stream_.get());
+ status = WriteBytes(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_STRING: {
- status = WriteString(field->number(), data, stream_.get());
+ status = WriteString(field.number(), data, stream_.get());
break;
}
case google::protobuf::Field_Kind_TYPE_ENUM: {
- status = WriteEnum(field->number(), data,
- typeinfo_->GetEnumByTypeUrl(field->type_url()),
+ status = WriteEnum(field.number(), data,
+ typeinfo_->GetEnumByTypeUrl(field.type_url()),
stream_.get());
break;
}
@@ -604,7 +645,7 @@ ProtoWriter* ProtoWriter::RenderDataPiece(StringPiece name,
}
if (!status.ok()) {
- InvalidValue(google::protobuf::Field_Kind_Name(field->kind()),
+ InvalidValue(google::protobuf::Field_Kind_Name(field.kind()),
status.error_message());
}
@@ -612,29 +653,6 @@ ProtoWriter* ProtoWriter::RenderDataPiece(StringPiece name,
return this;
}
-bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
- StringPiece unnormalized_name) {
- if (element_ == NULL) return true;
-
- if (field.oneof_index() > 0) {
- if (element_->IsOneofIndexTaken(field.oneof_index())) {
- InvalidValue(
- "oneof",
- StrCat("oneof field '",
- element_->type().oneofs(field.oneof_index() - 1),
- "' is already set. Cannot set '", unnormalized_name, "'"));
- return false;
- }
- element_->TakeOneofIndex(field.oneof_index());
- }
- return true;
-}
-
-bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) {
- return field.cardinality() ==
- google::protobuf::Field_Cardinality_CARDINALITY_REPEATED;
-}
-
const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name,
bool is_list) {
if (invalid_depth_ > 0) {
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index e631e56f..957565e7 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -106,10 +106,12 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoWriter* RenderString(StringPiece name, StringPiece value) {
- return RenderDataPiece(name, DataPiece(value));
+ return RenderDataPiece(name,
+ DataPiece(value, use_strict_base64_decoding()));
}
virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) {
- return RenderDataPiece(name, DataPiece(value, false));
+ return RenderDataPiece(
+ name, DataPiece(value, false, use_strict_base64_decoding()));
}
virtual ProtoWriter* RenderNull(StringPiece name) {
return RenderDataPiece(name, DataPiece::NullData());
@@ -126,7 +128,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
}
// When true, we finished writing to output a complete message.
- bool done() const { return done_; }
+ bool done() { return done_; }
// Returns the proto stream object.
google::protobuf::io::CodedOutputStream* stream() { return stream_.get(); }
@@ -266,6 +268,19 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
// Returns true if the field is repeated.
bool IsRepeated(const google::protobuf::Field& field);
+ // Starts an object given the field and the enclosing type.
+ ProtoWriter* StartObjectField(const google::protobuf::Field& field,
+ const google::protobuf::Type& type);
+
+ // Starts a list given the field and the enclosing type.
+ ProtoWriter* StartListField(const google::protobuf::Field& field,
+ const google::protobuf::Type& type);
+
+ // Renders a primitve field given the field and the enclosing type.
+ ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field,
+ const google::protobuf::Type& type,
+ const DataPiece& value);
+
private:
// Variables for describing the structure of the input tree:
// master_type_: descriptor for the whole protobuf message.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 034d616f..1f3781a4 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -70,6 +70,9 @@ using util::Status;
using util::StatusOr;
namespace {
+
+static int kDefaultMaxRecursionDepth = 64;
+
// Finds a field with the given number. NULL if none found.
const google::protobuf::Field* FindFieldByNumber(
const google::protobuf::Type& type, int number);
@@ -83,6 +86,29 @@ const google::protobuf::EnumValue* FindEnumValueByNumber(
// Utility function to format nanos.
const string FormatNanos(uint32 nanos);
+
+StatusOr<string> MapKeyDefaultValueAsString(
+ const google::protobuf::Field& field) {
+ switch (field.kind()) {
+ case google::protobuf::Field_Kind_TYPE_BOOL:
+ return string("false");
+ case google::protobuf::Field_Kind_TYPE_INT32:
+ case google::protobuf::Field_Kind_TYPE_INT64:
+ case google::protobuf::Field_Kind_TYPE_UINT32:
+ case google::protobuf::Field_Kind_TYPE_UINT64:
+ case google::protobuf::Field_Kind_TYPE_SINT32:
+ case google::protobuf::Field_Kind_TYPE_SINT64:
+ case google::protobuf::Field_Kind_TYPE_SFIXED32:
+ case google::protobuf::Field_Kind_TYPE_SFIXED64:
+ case google::protobuf::Field_Kind_TYPE_FIXED32:
+ case google::protobuf::Field_Kind_TYPE_FIXED64:
+ return string("0");
+ case google::protobuf::Field_Kind_TYPE_STRING:
+ return string();
+ default:
+ return Status(util::error::INTERNAL, "Invalid map key type.");
+ }
+}
} // namespace
@@ -92,14 +118,23 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
: stream_(stream),
typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
own_typeinfo_(true),
- type_(type) {
+ type_(type),
+ use_lower_camel_for_enums_(false),
+ recursion_depth_(0),
+ max_recursion_depth_(kDefaultMaxRecursionDepth) {
GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
}
ProtoStreamObjectSource::ProtoStreamObjectSource(
google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
const google::protobuf::Type& type)
- : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) {
+ : stream_(stream),
+ typeinfo_(typeinfo),
+ own_typeinfo_(false),
+ type_(type),
+ use_lower_camel_for_enums_(false),
+ recursion_depth_(0),
+ max_recursion_depth_(kDefaultMaxRecursionDepth) {
GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
}
@@ -238,9 +273,21 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
map_key = ReadFieldValueAsString(*field);
} else if (field->number() == 2) {
if (map_key.empty()) {
- return Status(util::error::INTERNAL, "Map key must be non-empty");
+ // An absent map key is treated as the default.
+ const google::protobuf::Field* key_field =
+ FindFieldByNumber(*field_type, 1);
+ if (key_field == NULL) {
+ // The Type info for this map entry is incorrect. It should always
+ // have a field named "key" and with field number 1.
+ return Status(util::error::INTERNAL, "Invalid map entry.");
+ }
+ ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
}
RETURN_IF_ERROR(RenderField(field, map_key, ow));
+ } else {
+ // The Type info for this map entry is incorrect. It should contain
+ // exactly two fields with field number 1 and 2.
+ return Status(util::error::INTERNAL, "Invalid map entry.");
}
}
stream_->PopLimit(old_limit);
@@ -266,7 +313,7 @@ Status ProtoStreamObjectSource::RenderTimestamp(
pair<int64, int32> p = os->ReadSecondsAndNanos(type);
int64 seconds = p.first;
int32 nanos = p.second;
- if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+ if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
return Status(
util::error::INTERNAL,
StrCat("Timestamp seconds exceeds limit for field: ", field_name));
@@ -290,7 +337,7 @@ Status ProtoStreamObjectSource::RenderDuration(
pair<int64, int32> p = os->ReadSecondsAndNanos(type);
int64 seconds = p.first;
int32 nanos = p.second;
- if (seconds > kMaxSeconds || seconds < kMinSeconds) {
+ if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
return Status(
util::error::INTERNAL,
StrCat("Duration seconds exceeds limit for field: ", field_name));
@@ -701,7 +748,9 @@ Status ProtoStreamObjectSource::RenderField(
if (use_type_renderer) {
RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
} else {
+ RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
+ --recursion_depth_;
}
if (!stream_->ConsumedEntireMessage()) {
return Status(util::error::INVALID_ARGUMENT,
@@ -807,7 +856,10 @@ Status ProtoStreamObjectSource::RenderNonMessageField(
const google::protobuf::EnumValue* enum_value =
FindEnumValueByNumber(*en, buffer32);
if (enum_value != NULL) {
- ow->RenderString(field_name, enum_value->name());
+ if (use_lower_camel_for_enums_)
+ ow->RenderString(field_name, ToCamelCase(enum_value->name()));
+ else
+ ow->RenderString(field_name, enum_value->name());
}
} else {
GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url();
@@ -994,6 +1046,17 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
return std::pair<int64, int32>(signed_seconds, signed_nanos);
}
+Status ProtoStreamObjectSource::IncrementRecursionDepth(
+ StringPiece type_name, StringPiece field_name) const {
+ if (++recursion_depth_ > max_recursion_depth_) {
+ return Status(
+ util::error::INVALID_ARGUMENT,
+ StrCat("Message too deep. Max recursion depth reached for type '",
+ type_name, "', field '", field_name, "'"));
+ }
+ return Status::OK;
+}
+
namespace {
// TODO(skarvaje): Speed this up by not doing a linear scan.
const google::protobuf::Field* FindFieldByNumber(
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 78defa1d..d7d4347b 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -82,6 +82,41 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
+ // Sets whether or not to use lowerCamelCase casing for enum values. If set to
+ // false, enum values are output without any case conversions.
+ //
+ // For example, if we have an enum:
+ // enum Type {
+ // ACTION_AND_ADVENTURE = 1;
+ // }
+ // Type type = 20;
+ //
+ // And this option is set to true. Then the rendered "type" field will have
+ // the string "actionAndAdventure".
+ // {
+ // ...
+ // "type": "actionAndAdventure",
+ // ...
+ // }
+ //
+ // If set to false, the rendered "type" field will have the string
+ // "ACTION_AND_ADVENTURE".
+ // {
+ // ...
+ // "type": "ACTION_AND_ADVENTURE",
+ // ...
+ // }
+ void set_use_lower_camel_for_enums(bool value) {
+ use_lower_camel_for_enums_ = value;
+ }
+
+ // Sets the max recursion depth of proto message to be deserialized. Proto
+ // messages over this depth will fail to be deserialized.
+ // Default value is 64.
+ void set_max_recursion_depth(int max_depth) {
+ max_recursion_depth_ = max_depth;
+ }
+
protected:
// Writes a proto2 Message to the ObjectWriter. When the given end_tag is
// found this method will complete, allowing it to be used for parsing both
@@ -223,6 +258,12 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
std::pair<int64, int32> ReadSecondsAndNanos(
const google::protobuf::Type& type) const;
+ // Helper function to check recursion depth and increment it. It will return
+ // Status::OK if the current depth is allowed. Otherwise an error is returned.
+ // type_name and field_name are used for error reporting.
+ util::Status IncrementRecursionDepth(StringPiece type_name,
+ StringPiece field_name) const;
+
// Input stream to read from. Ownership rests with the caller.
google::protobuf::io::CodedInputStream* stream_;
@@ -237,6 +278,15 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
const google::protobuf::Type& type_;
+ // Whether to render enums using lowerCamelCase. Defaults to false.
+ bool use_lower_camel_for_enums_;
+
+ // Tracks current recursion depth.
+ mutable int recursion_depth_;
+
+ // Maximum allowed recursion depth.
+ int max_recursion_depth_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
};
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 561f6763..3f6fdf97 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -50,6 +50,7 @@
#include <google/protobuf/util/internal/testdata/anys.pb.h>
#include <google/protobuf/util/internal/testdata/maps.pb.h>
#include <google/protobuf/util/internal/testdata/struct.pb.h>
+#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
#include <gtest/gtest.h>
@@ -69,12 +70,15 @@ using google::protobuf::testing::Author;
using google::protobuf::testing::BadAuthor;
using google::protobuf::testing::BadNestedBook;
using google::protobuf::testing::Book;
+using google::protobuf::testing::Cyclic;
using google::protobuf::testing::Book_Label;
using google::protobuf::testing::NestedBook;
using google::protobuf::testing::PackedPrimitive;
using google::protobuf::testing::Primitive;
using google::protobuf::testing::more_author;
using google::protobuf::testing::maps::MapOut;
+using google::protobuf::testing::maps::MapOutWireFormat;
+using google::protobuf::testing::timestampduration::TimestampDuration;
using google::protobuf::testing::anys::AnyOut;
using google::protobuf::testing::anys::AnyM;
using google::protobuf::testing::FieldMaskTest;
@@ -92,7 +96,11 @@ string GetTypeUrl(const Descriptor* descriptor) {
class ProtostreamObjectSourceTest
: public ::testing::TestWithParam<testing::TypeInfoSource> {
protected:
- ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) {
+ ProtostreamObjectSourceTest()
+ : helper_(GetParam()),
+ mock_(),
+ ow_(&mock_),
+ use_lower_camel_for_enums_(false) {
helper_.ResetTypeInfo(Book::descriptor());
}
@@ -112,6 +120,8 @@ class ProtostreamObjectSourceTest
google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
+ if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
+ os->set_max_recursion_depth(64);
return os->WriteTo(&mock_);
}
@@ -256,10 +266,13 @@ class ProtostreamObjectSourceTest
return primitive;
}
+ void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
+
testing::TypeInfoTestHelper helper_;
::testing::NiceMock<MockObjectWriter> mock_;
ExpectingObjectWriter ow_;
+ bool use_lower_camel_for_enums_;
};
INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
@@ -461,6 +474,52 @@ TEST_P(ProtostreamObjectSourceTest,
DoTest(book, Book::descriptor());
}
+TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputTest) {
+ Book book;
+ book.set_type(Book::ACTION_AND_ADVENTURE);
+
+ UseLowerCamelForEnums();
+
+ ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
+ DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
+ Book book;
+ book.set_type(Book::ACTION_AND_ADVENTURE);
+ ow_.StartObject("")
+ ->RenderString("type", "ACTION_AND_ADVENTURE")
+ ->EndObject();
+ DoTest(book, Book::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
+ Cyclic cyclic;
+ cyclic.set_m_int(123);
+
+ Book* book = cyclic.mutable_m_book();
+ book->set_title("book title");
+ Cyclic* current = cyclic.mutable_m_cyclic();
+ Author* current_author = cyclic.add_m_author();
+ for (int i = 0; i < 63; ++i) {
+ Author* next = current_author->add_friend_();
+ next->set_id(i);
+ next->set_name(StrCat("author_name_", i));
+ next->set_alive(true);
+ current_author = next;
+ }
+
+ // Recursive message with depth (65) > max (max is 64).
+ for (int i = 0; i < 64; ++i) {
+ Cyclic* next = current->mutable_m_cyclic();
+ next->set_m_str(StrCat("count_", i));
+ current = next;
+ }
+
+ Status status = ExecuteTest(cyclic, Cyclic::descriptor());
+ EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
+}
+
class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
protected:
ProtostreamObjectSourceMapsTest() {
@@ -541,6 +600,67 @@ TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
DoTest(out, MapOut::descriptor());
}
+TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
+ // MapOutWireFormat has the same wire representation with MapOut but uses
+ // repeated message fields to represent map fields so we can intentionally
+ // leave out the key field or the value field of a map entry.
+ MapOutWireFormat out;
+ // Create some map entries without keys. They will be rendered with the
+ // default values ("" for strings, "0" for integers, etc.).
+ // {
+ // "map1": {
+ // "": {
+ // "foo": "foovalue"
+ // }
+ // },
+ // "map2": {
+ // "": {
+ // "map1": {
+ // "nested_key1": {
+ // "foo": "nested_foo"
+ // }
+ // }
+ // }
+ // },
+ // "map3": {
+ // "0": "one one one"
+ // },
+ // "map4": {
+ // "false": "bool"
+ // }
+ // }
+ out.add_map1()->mutable_value()->set_foo("foovalue");
+ MapOut* nested = out.add_map2()->mutable_value();
+ (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
+ out.add_map3()->set_value("one one one");
+ out.add_map4()->set_value("bool");
+
+ ow_.StartObject("")
+ ->StartObject("map1")
+ ->StartObject("")
+ ->RenderString("foo", "foovalue")
+ ->EndObject()
+ ->EndObject()
+ ->StartObject("map2")
+ ->StartObject("")
+ ->StartObject("map1")
+ ->StartObject("nested_key1")
+ ->RenderString("foo", "nested_foo")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject()
+ ->EndObject()
+ ->StartObject("map3")
+ ->RenderString("0", "one one one")
+ ->EndObject()
+ ->StartObject("map4")
+ ->RenderString("false", "bool")
+ ->EndObject()
+ ->EndObject();
+
+ DoTest(out, MapOut::descriptor());
+}
+
class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
protected:
ProtostreamObjectSourceAnysTest() {
@@ -824,6 +944,63 @@ TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
DoTest(out, FieldMaskTest::descriptor());
}
+class ProtostreamObjectSourceTimestampTest
+ : public ProtostreamObjectSourceTest {
+ protected:
+ ProtostreamObjectSourceTimestampTest() {
+ helper_.ResetTypeInfo(TimestampDuration::descriptor());
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtostreamObjectSourceTimestampTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
+ TimestampDuration out;
+ google::protobuf::Timestamp* ts = out.mutable_ts();
+ // Min allowed seconds - 1
+ ts->set_seconds(kTimestampMinSeconds - 1);
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, TimestampDuration::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
+ TimestampDuration out;
+ google::protobuf::Timestamp* ts = out.mutable_ts();
+ // Max allowed seconds + 1
+ ts->set_seconds(kTimestampMaxSeconds + 1);
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, TimestampDuration::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
+ TimestampDuration out;
+ google::protobuf::Duration* dur = out.mutable_dur();
+ // Min allowed seconds - 1
+ dur->set_seconds(kDurationMinSeconds - 1);
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, TimestampDuration::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
+TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
+ TimestampDuration out;
+ google::protobuf::Duration* dur = out.mutable_dur();
+ // Min allowed seconds + 1
+ dur->set_seconds(kDurationMaxSeconds + 1);
+ ow_.StartObject("");
+
+ Status status = ExecuteTest(out, TimestampDuration::descriptor());
+ EXPECT_EQ(util::error::INTERNAL, status.error_code());
+}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 786bf0be..97a7909a 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -58,17 +58,20 @@ using util::StatusOr;
ProtoStreamObjectWriter::ProtoStreamObjectWriter(
TypeResolver* type_resolver, const google::protobuf::Type& type,
- strings::ByteSink* output, ErrorListener* listener)
+ strings::ByteSink* output, ErrorListener* listener,
+ const ProtoStreamObjectWriter::Options& options)
: ProtoWriter(type_resolver, type, output, listener),
master_type_(type),
- current_(NULL) {}
+ current_(NULL),
+ options_(options) {}
ProtoStreamObjectWriter::ProtoStreamObjectWriter(
const TypeInfo* typeinfo, const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener)
: ProtoWriter(typeinfo, type, output, listener),
master_type_(type),
- current_(NULL) {}
+ current_(NULL),
+ options_(ProtoStreamObjectWriter::Options::Defaults()) {}
ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
if (current_ == NULL) return;
@@ -179,7 +182,8 @@ ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
data_(),
output_(&data_),
depth_(0),
- has_injected_value_message_(false) {}
+ is_well_known_type_(false),
+ well_known_type_render_(NULL) {}
ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
@@ -197,10 +201,19 @@ void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
parent_->master_type_.name()));
invalid_ = true;
}
- } else if (!has_injected_value_message_ || depth_ != 1 || name != "value") {
- // We don't propagate to ow_ StartObject("value") calls for nested Anys or
- // Struct at depth 1 as they are nested one level deep with an injected
+ } else if (is_well_known_type_ && depth_ == 1) {
+ // For well-known types, the only other field besides "@type" should be a
// "value" field.
+ if (name != "value" && !invalid_) {
+ parent_->InvalidValue("Any",
+ "Expect a \"value\" field for well-known types.");
+ invalid_ = true;
+ }
+ ow_->StartObject("");
+ } else {
+ // Forward the call to the child writer if:
+ // 1. the type is not a well-known type.
+ // 2. or, we are in a nested Any, Struct, or Value object.
ow_->StartObject(name);
}
}
@@ -208,10 +221,9 @@ void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
--depth_;
// As long as depth_ >= 0, we know we haven't reached the end of Any.
- // Propagate these EndObject() calls to the contained ow_. If we are in a
- // nested Any or Struct type, ignore the second to last EndObject call (depth_
- // == -1)
- if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) {
+ // Propagate these EndObject() calls to the contained ow_. For regular
+ // message types, we propagate the end of Any as well.
+ if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) {
ow_->EndObject();
}
// A negative depth_ implies that we have reached the end of Any
@@ -233,6 +245,13 @@ void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
parent_->master_type_.name()));
invalid_ = true;
}
+ } else if (is_well_known_type_ && depth_ == 1) {
+ if (name != "value" && !invalid_) {
+ parent_->InvalidValue("Any",
+ "Expect a \"value\" field for well-known types.");
+ invalid_ = true;
+ }
+ ow_->StartList("");
} else {
ow_->StartList(name);
}
@@ -263,17 +282,27 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
parent_->master_type_.name()));
invalid_ = true;
}
- } else {
- // Check to see if the data needs to be rendered with well-known-type
- // renderer.
- const TypeRenderer* type_renderer =
- FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name()));
- if (type_renderer) {
- Status status = (*type_renderer)(ow_.get(), value);
- if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
+ } else if (depth_ == 0 && is_well_known_type_) {
+ if (name != "value" && !invalid_) {
+ parent_->InvalidValue("Any",
+ "Expect a \"value\" field for well-known types.");
+ invalid_ = true;
+ }
+ if (well_known_type_render_ == NULL) {
+ // Only Any and Struct don't have a special type render but both of
+ // them expect a JSON object (i.e., a StartObject() call).
+ if (!invalid_) {
+ parent_->InvalidValue("Any", "Expect a JSON object.");
+ invalid_ = true;
+ }
} else {
- ow_->RenderDataPiece(name, value);
+ ow_->ProtoWriter::StartObject("");
+ Status status = (*well_known_type_render_)(ow_.get(), value);
+ if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
+ ow_->ProtoWriter::EndObject();
}
+ } else {
+ ow_->RenderDataPiece(name, value);
}
}
@@ -302,19 +331,31 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
// At this point, type is never null.
const google::protobuf::Type* type = resolved_type.ValueOrDie();
- // If this is the case of an Any in an Any or Struct in an Any, we need to
- // expect a StartObject call with "value" while we're at depth_ 0, which we
- // should ignore (not propagate to our nested object writer). We also need to
- // ignore the second-to-last EndObject call, and not propagate that either.
- if (type->name() == kAnyType || type->name() == kStructType) {
- has_injected_value_message_ = true;
+ well_known_type_render_ = FindTypeRenderer(type_url_);
+ if (well_known_type_render_ != NULL ||
+ // Explicitly list Any and Struct here because they don't have a
+ // custom renderer.
+ type->name() == kAnyType || type->name() == kStructType) {
+ is_well_known_type_ = true;
}
// Create our object writer and initialize it with the first StartObject
// call.
ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
parent_->listener()));
- ow_->StartObject("");
+
+ // Don't call StartObject() for well-known types yet. Depending on the
+ // type of actual data, we may not need to call StartObject(). For
+ // example:
+ // {
+ // "@type": "type.googleapis.com/google.protobuf.Value",
+ // "value": [1, 2, 3],
+ // }
+ // With the above JSON representation, we will only call StartList() on the
+ // contained ow_.
+ if (!is_well_known_type_) {
+ ow_->StartObject("");
+ }
}
void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
@@ -439,7 +480,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
// name):
// { "key": "<name>", "value": {
Push("", Item::MESSAGE, false, false);
- ProtoWriter::RenderDataPiece("key", DataPiece(name));
+ ProtoWriter::RenderDataPiece("key",
+ DataPiece(name, use_strict_base64_decoding()));
Push("value", Item::MESSAGE, true, false);
// Make sure we are valid so far after starting map fields.
@@ -604,7 +646,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
// Render
// { "key": "<name>", "value": {
Push("", Item::MESSAGE, false, false);
- ProtoWriter::RenderDataPiece("key", DataPiece(name));
+ ProtoWriter::RenderDataPiece("key",
+ DataPiece(name, use_strict_base64_decoding()));
Push("value", Item::MESSAGE, true, false);
// Make sure we are valid after pushing all above items.
@@ -758,8 +801,36 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
string struct_field_name;
switch (data.type()) {
// Our JSON parser parses numbers as either int64, uint64, or double.
- case DataPiece::TYPE_INT64:
- case DataPiece::TYPE_UINT64:
+ case DataPiece::TYPE_INT64: {
+ // If the option to treat integers as strings is set, then render them as
+ // strings. Otherwise, fallback to rendering them as double.
+ if (ow->options_.struct_integers_as_strings) {
+ StatusOr<int64> int_value = data.ToInt64();
+ if (int_value.ok()) {
+ ow->ProtoWriter::RenderDataPiece(
+ "string_value",
+ DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+ return Status::OK;
+ }
+ }
+ struct_field_name = "number_value";
+ break;
+ }
+ case DataPiece::TYPE_UINT64: {
+ // If the option to treat integers as strings is set, then render them as
+ // strings. Otherwise, fallback to rendering them as double.
+ if (ow->options_.struct_integers_as_strings) {
+ StatusOr<uint64> int_value = data.ToUint64();
+ if (int_value.ok()) {
+ ow->ProtoWriter::RenderDataPiece(
+ "string_value",
+ DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
+ return Status::OK;
+ }
+ }
+ struct_field_name = "number_value";
+ break;
+ }
case DataPiece::TYPE_DOUBLE: {
struct_field_name = "number_value";
break;
@@ -812,7 +883,7 @@ Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
StringPiece path) {
ow->ProtoWriter::RenderDataPiece(
- "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase)));
+ "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
return Status::OK;
}
@@ -828,7 +899,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
// conversions as much as possible. Because ToSnakeCase sometimes returns the
// wrong value.
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
- google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
+ ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
return DecodeCompactFieldMaskPaths(data.str(), callback.get());
}
@@ -871,7 +942,7 @@ Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
nanos = sign * nanos;
int64 seconds = sign * unsigned_seconds;
- if (seconds > kMaxSeconds || seconds < kMinSeconds ||
+ if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
}
@@ -925,7 +996,8 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
// Render an item in repeated map list.
// { "key": "<name>", "value":
Push("", Item::MESSAGE, false, false);
- ProtoWriter::RenderDataPiece("key", DataPiece(name));
+ ProtoWriter::RenderDataPiece("key",
+ DataPiece(name, use_strict_base64_decoding()));
field = Lookup("value");
if (field == NULL) {
GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
@@ -952,6 +1024,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
// not of the google.protobuf.NullType type, we do nothing.
if (data.type() == DataPiece::TYPE_NULL &&
field->type_url() != kStructNullValueTypeUrl) {
+ Pop();
return this;
}
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index 08ac6e33..e1162d43 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -74,10 +74,30 @@ class ObjectLocationTracker;
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
public:
+ // Options that control ProtoStreamObjectWriter class's behavior.
+ struct Options {
+ // Treats integer inputs in google.protobuf.Struct as strings. Normally,
+ // integer values are returned in double field "number_value" of
+ // google.protobuf.Struct. However, this can cause precision loss for
+ // int64/uint64 inputs. This option is provided for cases that want to
+ // preserve integer precision.
+ bool struct_integers_as_strings;
+
+ Options() : struct_integers_as_strings(false) {}
+
+ // Default instance of Options with all options set to defaults.
+ static const Options& Defaults() {
+ static Options defaults;
+ return defaults;
+ }
+ };
+
// Constructor. Does not take ownership of any parameter passed in.
ProtoStreamObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
- strings::ByteSink* output, ErrorListener* listener);
+ strings::ByteSink* output, ErrorListener* listener,
+ const ProtoStreamObjectWriter::Options& options =
+ ProtoStreamObjectWriter::Options::Defaults());
virtual ~ProtoStreamObjectWriter();
// ObjectWriter methods.
@@ -147,9 +167,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
// The depth within the Any, so we can track when we're done.
int depth_;
- // True if the message type contained in Any has a special "value" message
- // injected. This is true for well-known message types like Any or Struct.
- bool has_injected_value_message_;
+ // True if the type is a well-known type. Well-known types in Any
+ // has a special formating:
+ // {
+ // "@type": "type.googleapis.com/google.protobuf.XXX",
+ // "value": <JSON representation of the type>,
+ // }
+ bool is_well_known_type_;
+ TypeRenderer* well_known_type_render_;
};
// Represents an item in a stack of items used to keep state between
@@ -301,6 +326,9 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
// The current element, variable for internal state processing.
google::protobuf::scoped_ptr<Item> current_;
+ // Reference to the options that control this class's behavior.
+ const ProtoStreamObjectWriter::Options options_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
};
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index 5f9ffb95..9a0dcde1 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -90,6 +90,12 @@ string GetTypeUrl(const Descriptor* descriptor) {
}
} // namespace
+#if __cplusplus >= 201103L
+ using std::get;
+#else
+ using std::tr1::get;
+#endif
+
class BaseProtoStreamObjectWriterTest
: public ::testing::TestWithParam<testing::TypeInfoSource> {
protected:
@@ -122,7 +128,13 @@ class BaseProtoStreamObjectWriterTest
GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
helper_.ResetTypeInfo(descriptors);
ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
- &listener_));
+ &listener_, options_));
+ }
+
+ void ResetTypeInfo(const Descriptor* descriptor) {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(descriptor);
+ ResetTypeInfo(descriptors);
}
virtual ~BaseProtoStreamObjectWriterTest() {}
@@ -155,16 +167,12 @@ class BaseProtoStreamObjectWriterTest
MockErrorListener listener_;
google::protobuf::scoped_ptr<GrowingArrayByteSink> output_;
google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
+ ProtoStreamObjectWriter::Options options_;
};
MATCHER_P(HasObjectLocation, expected,
"Verifies the expected object location") {
- string actual;
-#if __cplusplus >= 201103L
- actual = std::get<0>(arg).ToString();
-#else
- actual = std::tr1::get<0>(arg).ToString();
-#endif
+ string actual = get<0>(arg).ToString();
if (actual.compare(expected) == 0) return true;
*result_listener << "actual location is: " << actual;
return false;
@@ -289,8 +297,7 @@ TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) {
full.add_rep_double(-8.05L);
full.add_rep_bool(false);
- ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
- output_.get(), &listener_));
+ ResetTypeInfo(Primitive::descriptor());
ow_->StartObject("")
->RenderString("fix32", "101")
@@ -363,8 +370,7 @@ TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) {
full.set_float_(std::numeric_limits<float>::infinity());
full.set_str("-Infinity");
- ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
- output_.get(), &listener_));
+ ResetTypeInfo(Primitive::descriptor());
EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
StringPiece("\"Infinity\"")))
@@ -397,8 +403,7 @@ TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) {
full.set_float_(std::numeric_limits<float>::quiet_NaN());
full.set_str("NaN");
- ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
- output_.get(), &listener_));
+ ResetTypeInfo(Primitive::descriptor());
EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
StringPiece("\"NaN\"")))
@@ -887,6 +892,124 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseTimestamp) {
CheckOutput(timestamp);
}
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ ParseTimestampYearNotZeroPadded) {
+ TimestampDuration timestamp;
+ google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+ ts->set_seconds(-61665654145);
+ ts->set_nanos(33155000);
+
+ ow_->StartObject("")
+ ->RenderString("ts", "15-11-23T03:37:35.033155Z")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ ParseTimestampYearZeroPadded) {
+ TimestampDuration timestamp;
+ google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+ ts->set_seconds(-61665654145);
+ ts->set_nanos(33155000);
+
+ ow_->StartObject("")
+ ->RenderString("ts", "0015-11-23T03:37:35.033155Z")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ ParseTimestampWithPositiveOffset) {
+ TimestampDuration timestamp;
+ google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+ ts->set_seconds(1448249855);
+ ts->set_nanos(33155000);
+
+ ow_->StartObject("")
+ ->RenderString("ts", "2015-11-23T11:47:35.033155+08:10")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ ParseTimestampWithNegativeOffset) {
+ TimestampDuration timestamp;
+ google::protobuf::Timestamp* ts = timestamp.mutable_ts();
+ ts->set_seconds(1448249855);
+ ts->set_nanos(33155000);
+
+ ow_->StartObject("")
+ ->RenderString("ts", "2015-11-22T19:47:35.033155-07:50")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ TimestampWithInvalidOffset1) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: "
+ "2016-03-07T15:14:23+")));
+
+ ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ TimestampWithInvalidOffset2) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: "
+ "2016-03-07T15:14:23+08-10")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "2016-03-07T15:14:23+08-10")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ TimestampWithInvalidOffset3) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: "
+ "2016-03-07T15:14:23+24:10")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "2016-03-07T15:14:23+24:10")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
+ TimestampWithInvalidOffset4) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: "
+ "2016-03-07T15:14:23+04:60")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "2016-03-07T15:14:23+04:60")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
TimestampDuration timestamp;
@@ -937,10 +1060,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
StringPiece("Field 'ts', Invalid time format: "
- "-8032-10-18T00:00:00.000Z")));
+ "-8031-10-18T00:00:00.000Z")));
ow_->StartObject("")
- ->RenderString("ts", "-8032-10-18T00:00:00.000Z")
+ ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
->EndObject();
CheckOutput(timestamp);
}
@@ -996,6 +1119,22 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError7) {
CheckOutput(timestamp);
}
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) {
+ TimestampDuration timestamp;
+
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_,
+ StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format: "
+ "0-12-31T23:59:59.000Z")));
+
+ ow_->StartObject("")
+ ->RenderString("ts", "0-12-31T23:59:59.000Z")
+ ->EndObject();
+ CheckOutput(timestamp);
+}
+
TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseDuration) {
TimestampDuration duration;
google::protobuf::Duration* dur = duration.mutable_dur();
@@ -1105,7 +1244,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
class ProtoStreamObjectWriterStructTest
: public BaseProtoStreamObjectWriterTest {
protected:
- ProtoStreamObjectWriterStructTest() {
+ ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
+
+ // Resets ProtoWriter with current set of options and other state.
+ void ResetProtoWriter() {
vector<const Descriptor*> descriptors;
descriptors.push_back(StructType::descriptor());
descriptors.push_back(google::protobuf::Struct::descriptor());
@@ -1201,6 +1343,28 @@ TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
->EndObject();
}
+TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) {
+ StructType struct_type;
+ google::protobuf::Struct* s = struct_type.mutable_object();
+ s->mutable_fields()->operator[]("k1").set_number_value(123);
+ s->mutable_fields()->operator[]("k2").set_bool_value(true);
+ s->mutable_fields()->operator[]("k3").set_string_value("-222222222");
+ s->mutable_fields()->operator[]("k4").set_string_value("33333333");
+
+ options_.struct_integers_as_strings = true;
+ ResetProtoWriter();
+
+ ow_->StartObject("")
+ ->StartObject("object")
+ ->RenderDouble("k1", 123)
+ ->RenderBool("k2", true)
+ ->RenderInt64("k3", -222222222)
+ ->RenderUint64("k4", 33333333)
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(struct_type);
+}
+
class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
protected:
ProtoStreamObjectWriterMapTest()
@@ -1249,6 +1413,8 @@ class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
descriptors.push_back(google::protobuf::DoubleValue::descriptor());
descriptors.push_back(google::protobuf::Timestamp::descriptor());
descriptors.push_back(google::protobuf::Any::descriptor());
+ descriptors.push_back(google::protobuf::Value::descriptor());
+ descriptors.push_back(google::protobuf::Struct::descriptor());
ResetTypeInfo(descriptors);
}
};
@@ -1457,6 +1623,222 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
CheckOutput(any);
}
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "value": "abc"
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedPrimitiveValue) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+
+ ::google::protobuf::Value value;
+ value.set_string_value("abc");
+ any->PackFrom(value);
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->RenderString("value", "abc")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "value": {
+// "foo": "abc"
+// }
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedObjectValue) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+
+ ::google::protobuf::Value value;
+ (*value.mutable_struct_value()->mutable_fields())["foo"].set_string_value(
+ "abc");
+ any->PackFrom(value);
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->StartObject("value")
+ ->RenderString("foo", "abc")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "value": ["hello"],
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedArrayValue) {
+ AnyOut out;
+ ::google::protobuf::Any* any = out.mutable_any();
+
+ ::google::protobuf::Value value;
+ value.mutable_list_value()->add_values()->set_string_value("hello");
+ any->PackFrom(value);
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->StartList("value")
+ ->RenderString("", "hello")
+ ->EndList()
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(out);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "not_value": ""
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest,
+ AnyWellKnownTypesNoValueFieldForPrimitive) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("Any"),
+ StringPiece("Expect a \"value\" field for well-known types.")));
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->RenderString("not_value", "")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "not_value": {}
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForObject) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("Any"),
+ StringPiece("Expect a \"value\" field for well-known types.")));
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->StartObject("not_value")
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Value",
+// "not_value": [],
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("Any"),
+ StringPiece("Expect a \"value\" field for well-known types.")));
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
+ ->StartList("not_value")
+ ->EndList()
+ ->EndObject()
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Struct",
+// "value": "",
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) {
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+ StringPiece("Expect a JSON object.")));
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Struct");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Struct")
+ ->RenderString("value", "")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
+// Test the following case:
+//
+// {
+// "any": {
+// "@type": "type.googleapis.com/google.protobuf.Any",
+// "value": "",
+// }
+// }
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) {
+ EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
+ StringPiece("Expect a JSON object.")));
+ AnyOut any;
+ google::protobuf::Any* any_type = any.mutable_any();
+ any_type->set_type_url("type.googleapis.com/google.protobuf.Any");
+
+ ow_->StartObject("")
+ ->StartObject("any")
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
+ ->RenderString("value", "")
+ ->EndObject()
+ ->EndObject();
+ CheckOutput(any);
+}
+
class ProtoStreamObjectWriterFieldMaskTest
: public BaseProtoStreamObjectWriterTest {
protected:
diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto
index 82b81760..1cbbba47 100644
--- a/src/google/protobuf/util/internal/testdata/books.proto
+++ b/src/google/protobuf/util/internal/testdata/books.proto
@@ -56,6 +56,13 @@ message Book {
optional Publisher publisher = 9;
repeated Label labels = 10;
+ enum Type {
+ FICTION = 1;
+ KIDS = 2;
+ ACTION_AND_ADVENTURE = 3;
+ }
+ optional Type type = 11;
+
extensions 200 to 499;
}
@@ -169,3 +176,12 @@ message NestedBook {
message BadNestedBook {
repeated uint32 book = 1 [packed=true]; // Packed to optional message.
}
+
+// A recursively defined message.
+message Cyclic {
+ optional int32 m_int = 1;
+ optional string m_str = 2;
+ optional Book m_book = 3;
+ repeated Author m_author = 5;
+ optional Cyclic m_cyclic = 4;
+}
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
index 1b9c5154..49e18ed0 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -102,13 +102,13 @@ ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
}
ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
- const string& type_url, strings::ByteSink* output,
- ErrorListener* listener) {
+ const string& type_url, strings::ByteSink* output, ErrorListener* listener,
+ const ProtoStreamObjectWriter::Options& options) {
const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
- listener);
+ listener, options);
}
}
GOOGLE_LOG(FATAL) << "Can not reach here.";
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
index 6916a73b..1a279849 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.h
+++ b/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -39,8 +39,8 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
+#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/protostream_objectsource.h>
#include <google/protobuf/util/internal/protostream_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
@@ -77,9 +77,9 @@ class TypeInfoTestHelper {
ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
const string& type_url);
- ProtoStreamObjectWriter* NewProtoWriter(const string& type_url,
- strings::ByteSink* output,
- ErrorListener* listener);
+ ProtoStreamObjectWriter* NewProtoWriter(
+ const string& type_url, strings::ByteSink* output,
+ ErrorListener* listener, const ProtoStreamObjectWriter::Options& options);
DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url,
ObjectWriter* writer);
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 1ddf2487..ee7a51fc 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -222,6 +222,7 @@ string ToCamelCase(const StringPiece input) {
if (!result.empty() && is_cap &&
(!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
first_word = false;
+ result.push_back(input[i]);
} else {
result.push_back(ascii_tolower(input[i]));
continue;
@@ -231,9 +232,13 @@ string ToCamelCase(const StringPiece input) {
if (ascii_islower(input[i])) {
result.push_back(ascii_toupper(input[i]));
continue;
+ } else {
+ result.push_back(input[i]);
+ continue;
}
+ } else {
+ result.push_back(ascii_tolower(input[i]));
}
- result.push_back(input[i]);
}
return result;
}
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index c3b8d502..2659320a 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -102,6 +102,42 @@ util::Status BinaryToJsonString(TypeResolver* resolver,
options);
}
+namespace {
+class StatusErrorListener : public converter::ErrorListener {
+ public:
+ StatusErrorListener() : status_(util::Status::OK) {}
+ virtual ~StatusErrorListener() {}
+
+ util::Status GetStatus() { return status_; }
+
+ virtual void InvalidName(const converter::LocationTrackerInterface& loc,
+ StringPiece unknown_name, StringPiece message) {
+ status_ = util::Status(util::error::INVALID_ARGUMENT,
+ loc.ToString() + ": " + message.ToString());
+ }
+
+ virtual void InvalidValue(const converter::LocationTrackerInterface& loc,
+ StringPiece type_name, StringPiece value) {
+ status_ =
+ util::Status(util::error::INVALID_ARGUMENT,
+ loc.ToString() + ": invalid value " + value.ToString() +
+ " for type " + type_name.ToString());
+ }
+
+ virtual void MissingField(const converter::LocationTrackerInterface& loc,
+ StringPiece missing_name) {
+ status_ = util::Status(
+ util::error::INVALID_ARGUMENT,
+ loc.ToString() + ": missing field " + missing_name.ToString());
+ }
+
+ private:
+ util::Status status_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
+};
+} // namespace
+
util::Status JsonToBinaryStream(TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* json_input,
@@ -109,7 +145,7 @@ util::Status JsonToBinaryStream(TypeResolver* resolver,
google::protobuf::Type type;
RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
internal::ZeroCopyStreamByteSink sink(binary_output);
- converter::NoopErrorListener listener;
+ StatusErrorListener listener;
converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
&listener);
@@ -123,7 +159,7 @@ util::Status JsonToBinaryStream(TypeResolver* resolver,
}
RETURN_IF_ERROR(parser.FinishParse());
- return util::Status::OK;
+ return listener.GetStatus();
}
util::Status JsonToBinaryString(TypeResolver* resolver,
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index da68495f..a4d3cc98 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -77,8 +77,11 @@ class JsonUtilTest : public testing::Test {
bool FromJson(const string& json, Message* message) {
string binary;
- GOOGLE_CHECK_OK(JsonToBinaryString(
- resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary));
+ if (!JsonToBinaryString(resolver_.get(),
+ GetTypeUrl(message->GetDescriptor()), json, &binary)
+ .ok()) {
+ return false;
+ }
return message->ParseFromString(binary);
}
@@ -99,28 +102,36 @@ TEST_F(JsonUtilTest, TestWhitespaces) {
ToJson(m, options));
}
-// TODO(skarvaje): Uncomment after cl/96232915 is submitted.
-// TEST_F(JsonUtilTest, TestDefaultValues) {
- // TestMessage m;
- // JsonOptions options;
- // EXPECT_EQ("{}", ToJson(m, options));
- // options.always_print_primitive_fields = true;
- // EXPECT_EQ(
- // "{\"boolValue\":false,"
- // "\"int32Value\":0,"
- // "\"int64Value\":\"0\","
- // "\"uint32Value\":0,"
- // "\"uint64Value\":\"0\","
- // "\"floatValue\":0,"
- // "\"doubleValue\":0,"
- // "\"stringValue\":\"\","
- // "\"bytesValue\":\"\","
- // // TODO(xiaofeng): The default enum value should be FOO. I believe
- // // this is a bug in DefaultValueObjectWriter.
- // "\"enumValue\":null"
- // "}",
- // ToJson(m, options));
-// }
+TEST_F(JsonUtilTest, TestDefaultValues) {
+ TestMessage m;
+ JsonOptions options;
+ EXPECT_EQ("{}", ToJson(m, options));
+ options.always_print_primitive_fields = true;
+ EXPECT_EQ(
+ "{\"boolValue\":false,"
+ "\"int32Value\":0,"
+ "\"int64Value\":\"0\","
+ "\"uint32Value\":0,"
+ "\"uint64Value\":\"0\","
+ "\"floatValue\":0,"
+ "\"doubleValue\":0,"
+ "\"stringValue\":\"\","
+ "\"bytesValue\":\"\","
+ "\"enumValue\":\"FOO\","
+ "\"repeatedBoolValue\":[],"
+ "\"repeatedInt32Value\":[],"
+ "\"repeatedInt64Value\":[],"
+ "\"repeatedUint32Value\":[],"
+ "\"repeatedUint64Value\":[],"
+ "\"repeatedFloatValue\":[],"
+ "\"repeatedDoubleValue\":[],"
+ "\"repeatedStringValue\":[],"
+ "\"repeatedBytesValue\":[],"
+ "\"repeatedEnumValue\":[],"
+ "\"repeatedMessageValue\":[]"
+ "}",
+ ToJson(m, options));
+}
TEST_F(JsonUtilTest, ParseMessage) {
// Some random message but good enough to verify that the parsing warpper
@@ -158,6 +169,15 @@ TEST_F(JsonUtilTest, ParseMap) {
EXPECT_EQ(message.DebugString(), other.DebugString());
}
+TEST_F(JsonUtilTest, TestParseErrors) {
+ TestMessage m;
+ JsonOptions options;
+ // Parsing should fail if the field name can not be recognized.
+ EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m));
+ // Parsing should fail if the value is invalid.
+ EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m));
+}
+
typedef pair<char*, int> Segment;
// A ZeroCopyOutputStream that writes to multiple buffers.
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 0f879dc7..fe8119bf 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/any.h>
#include <google/protobuf/io/printer.h>
@@ -455,7 +456,9 @@ bool MessageDifferencer::Compare(
const Descriptor* descriptor2 = message2.GetDescriptor();
if (descriptor1 != descriptor2) {
GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
- << "descriptors.";
+ << "descriptors. "
+ << descriptor1->full_name() << " vs "
+ << descriptor2->full_name();
return false;
}
// Expand google.protobuf.Any payload if possible.
@@ -1021,7 +1024,7 @@ bool MessageDifferencer::UnpackAny(const Message& any,
any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
full_type_name);
if (desc == NULL) {
- GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found";
+ GOOGLE_DLOG(ERROR) << "Proto type '" << full_type_name << "' not found";
return false;
}
@@ -1031,7 +1034,7 @@ bool MessageDifferencer::UnpackAny(const Message& any,
data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
string serialized_value = reflection->GetString(any, value_field);
if (!(*data)->ParseFromString(serialized_value)) {
- GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name;
+ GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
return false;
}
return true;
@@ -1384,7 +1387,7 @@ bool MessageDifferencer::MatchRepeatedFieldIndices(
// algorithm will fail to find a maximum matching.
// Here we use the argumenting path algorithm.
MaximumMatcher::NodeMatchCallback* callback =
- google::protobuf::internal::NewPermanentCallback(
+ ::google::protobuf::internal::NewPermanentCallback(
this, &MessageDifferencer::IsMatch,
repeated_field, key_comparator,
&message1, &message2, parent_fields);
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 7f1093c8..f2517074 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -412,7 +412,7 @@ void WireFormatLite::WriteString(int field_number, const string& value,
io::CodedOutputStream* output) {
// String is for UTF-8 text only
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- GOOGLE_CHECK(value.size() <= kint32max);
+ GOOGLE_CHECK_LE(value.size(), kint32max);
output->WriteVarint32(value.size());
output->WriteString(value);
}
@@ -421,14 +421,14 @@ void WireFormatLite::WriteStringMaybeAliased(
io::CodedOutputStream* output) {
// String is for UTF-8 text only
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- GOOGLE_CHECK(value.size() <= kint32max);
+ GOOGLE_CHECK_LE(value.size(), kint32max);
output->WriteVarint32(value.size());
output->WriteRawMaybeAliased(value.data(), value.size());
}
void WireFormatLite::WriteBytes(int field_number, const string& value,
io::CodedOutputStream* output) {
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- GOOGLE_CHECK(value.size() <= kint32max);
+ GOOGLE_CHECK_LE(value.size(), kint32max);
output->WriteVarint32(value.size());
output->WriteString(value);
}
@@ -436,7 +436,7 @@ void WireFormatLite::WriteBytesMaybeAliased(
int field_number, const string& value,
io::CodedOutputStream* output) {
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- GOOGLE_CHECK(value.size() <= kint32max);
+ GOOGLE_CHECK_LE(value.size(), kint32max);
output->WriteVarint32(value.size());
output->WriteRawMaybeAliased(value.data(), value.size());
}
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 79493ca0..7bce21cf 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -274,8 +274,8 @@ inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
// The number of bytes each type occupies on the wire.
const int per_value_size = tag_size + sizeof(value);
- int elements_available = min(values->Capacity() - values->size(),
- size / per_value_size);
+ int elements_available =
+ std::min(values->Capacity() - values->size(), size / per_value_size);
int num_read = 0;
while (num_read < elements_available &&
(buffer = io::CodedInputStream::ExpectTagFromArray(
@@ -367,7 +367,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
bytes_limit = input->BytesUntilLimit();
} else {
bytes_limit =
- min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
+ std::min(bytes_limit, static_cast<int64>(input->BytesUntilLimit()));
}
if (bytes_limit >= new_bytes) {
// Fast-path that pre-allocates *values to the final size.
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 15c37556..4e4add66 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -45,6 +45,7 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 212dd219..60801423 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -263,10 +263,11 @@ void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() {
"e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013"
"UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022"
"\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001"
- " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BS\n\023com"
- ".google.protobufB\rWrappersProtoP\001\240\001\001\370\001\001\242"
- "\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006"
- "proto3", 406);
+ " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\177\n\023com"
+ ".google.protobufB\rWrappersProtoP\001Z*githu"
+ "b.com/golang/protobuf/ptypes/wrappers\240\001\001"
+ "\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTyp"
+ "esb\006proto3", 450);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
DoubleValue::default_instance_ = new DoubleValue();
@@ -387,12 +388,13 @@ DoubleValue* DoubleValue::New(::google::protobuf::Arena* arena) const {
}
void DoubleValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
value_ = 0;
}
bool DoubleValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.DoubleValue)
for (;;) {
@@ -459,6 +461,7 @@ void DoubleValue::SerializeWithCachedSizes(
}
int DoubleValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue)
int total_size = 0;
// optional double value = 1;
@@ -473,18 +476,22 @@ int DoubleValue::ByteSize() const {
}
void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const DoubleValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DoubleValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DoubleValue)
MergeFrom(*source);
}
}
void DoubleValue::MergeFrom(const DoubleValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -492,12 +499,14 @@ void DoubleValue::MergeFrom(const DoubleValue& from) {
}
void DoubleValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DoubleValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void DoubleValue::CopyFrom(const DoubleValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DoubleValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -637,12 +646,13 @@ FloatValue* FloatValue::New(::google::protobuf::Arena* arena) const {
}
void FloatValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
value_ = 0;
}
bool FloatValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.FloatValue)
for (;;) {
@@ -709,6 +719,7 @@ void FloatValue::SerializeWithCachedSizes(
}
int FloatValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue)
int total_size = 0;
// optional float value = 1;
@@ -723,18 +734,22 @@ int FloatValue::ByteSize() const {
}
void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const FloatValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FloatValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FloatValue)
MergeFrom(*source);
}
}
void FloatValue::MergeFrom(const FloatValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -742,12 +757,14 @@ void FloatValue::MergeFrom(const FloatValue& from) {
}
void FloatValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FloatValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void FloatValue::CopyFrom(const FloatValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FloatValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -887,12 +904,13 @@ Int64Value* Int64Value::New(::google::protobuf::Arena* arena) const {
}
void Int64Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
value_ = GOOGLE_LONGLONG(0);
}
bool Int64Value::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Int64Value)
for (;;) {
@@ -959,6 +977,7 @@ void Int64Value::SerializeWithCachedSizes(
}
int Int64Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value)
int total_size = 0;
// optional int64 value = 1;
@@ -975,18 +994,22 @@ int Int64Value::ByteSize() const {
}
void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Int64Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int64Value)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int64Value)
MergeFrom(*source);
}
}
void Int64Value::MergeFrom(const Int64Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -994,12 +1017,14 @@ void Int64Value::MergeFrom(const Int64Value& from) {
}
void Int64Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int64Value)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Int64Value::CopyFrom(const Int64Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int64Value)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1139,12 +1164,13 @@ UInt64Value* UInt64Value::New(::google::protobuf::Arena* arena) const {
}
void UInt64Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
value_ = GOOGLE_ULONGLONG(0);
}
bool UInt64Value::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.UInt64Value)
for (;;) {
@@ -1211,6 +1237,7 @@ void UInt64Value::SerializeWithCachedSizes(
}
int UInt64Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value)
int total_size = 0;
// optional uint64 value = 1;
@@ -1227,18 +1254,22 @@ int UInt64Value::ByteSize() const {
}
void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const UInt64Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt64Value)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt64Value)
MergeFrom(*source);
}
}
void UInt64Value::MergeFrom(const UInt64Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -1246,12 +1277,14 @@ void UInt64Value::MergeFrom(const UInt64Value& from) {
}
void UInt64Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt64Value)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void UInt64Value::CopyFrom(const UInt64Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt64Value)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1391,12 +1424,13 @@ Int32Value* Int32Value::New(::google::protobuf::Arena* arena) const {
}
void Int32Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
value_ = 0;
}
bool Int32Value::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Int32Value)
for (;;) {
@@ -1463,6 +1497,7 @@ void Int32Value::SerializeWithCachedSizes(
}
int Int32Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value)
int total_size = 0;
// optional int32 value = 1;
@@ -1479,18 +1514,22 @@ int Int32Value::ByteSize() const {
}
void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const Int32Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Int32Value)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Int32Value)
MergeFrom(*source);
}
}
void Int32Value::MergeFrom(const Int32Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -1498,12 +1537,14 @@ void Int32Value::MergeFrom(const Int32Value& from) {
}
void Int32Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Int32Value)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Int32Value::CopyFrom(const Int32Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int32Value)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1643,12 +1684,13 @@ UInt32Value* UInt32Value::New(::google::protobuf::Arena* arena) const {
}
void UInt32Value::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
value_ = 0u;
}
bool UInt32Value::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.UInt32Value)
for (;;) {
@@ -1715,6 +1757,7 @@ void UInt32Value::SerializeWithCachedSizes(
}
int UInt32Value::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value)
int total_size = 0;
// optional uint32 value = 1;
@@ -1731,18 +1774,22 @@ int UInt32Value::ByteSize() const {
}
void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const UInt32Value* source =
::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UInt32Value)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UInt32Value)
MergeFrom(*source);
}
}
void UInt32Value::MergeFrom(const UInt32Value& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -1750,12 +1797,14 @@ void UInt32Value::MergeFrom(const UInt32Value& from) {
}
void UInt32Value::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UInt32Value)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void UInt32Value::CopyFrom(const UInt32Value& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt32Value)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -1895,12 +1944,13 @@ BoolValue* BoolValue::New(::google::protobuf::Arena* arena) const {
}
void BoolValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
value_ = false;
}
bool BoolValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.BoolValue)
for (;;) {
@@ -1967,6 +2017,7 @@ void BoolValue::SerializeWithCachedSizes(
}
int BoolValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue)
int total_size = 0;
// optional bool value = 1;
@@ -1981,18 +2032,22 @@ int BoolValue::ByteSize() const {
}
void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const BoolValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BoolValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BoolValue)
MergeFrom(*source);
}
}
void BoolValue::MergeFrom(const BoolValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value() != 0) {
set_value(from.value());
@@ -2000,12 +2055,14 @@ void BoolValue::MergeFrom(const BoolValue& from) {
}
void BoolValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BoolValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void BoolValue::CopyFrom(const BoolValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BoolValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2147,12 +2204,13 @@ StringValue* StringValue::New(::google::protobuf::Arena* arena) const {
}
void StringValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
bool StringValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.StringValue)
for (;;) {
@@ -2232,6 +2290,7 @@ void StringValue::SerializeWithCachedSizes(
}
int StringValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue)
int total_size = 0;
// optional string value = 1;
@@ -2248,18 +2307,22 @@ int StringValue::ByteSize() const {
}
void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const StringValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.StringValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.StringValue)
MergeFrom(*source);
}
}
void StringValue::MergeFrom(const StringValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value().size() > 0) {
set_value(from.value());
@@ -2267,12 +2330,14 @@ void StringValue::MergeFrom(const StringValue& from) {
}
void StringValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.StringValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void StringValue::CopyFrom(const StringValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.StringValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2348,10 +2413,12 @@ void StringValue::clear_value() {
return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
::std::string* StringValue::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value)
return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
::std::string* StringValue::unsafe_arena_release_value() {
+ // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value)
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
@@ -2377,7 +2444,7 @@ void StringValue::clear_value() {
}
value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
value, GetArenaNoVirtual());
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value)
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -2464,12 +2531,13 @@ BytesValue* BytesValue::New(::google::protobuf::Arena* arena) const {
}
void BytesValue::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
bool BytesValue::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.BytesValue)
for (;;) {
@@ -2537,6 +2605,7 @@ void BytesValue::SerializeWithCachedSizes(
}
int BytesValue::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue)
int total_size = 0;
// optional bytes value = 1;
@@ -2553,18 +2622,22 @@ int BytesValue::ByteSize() const {
}
void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const BytesValue* source =
::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
&from);
if (source == NULL) {
+ // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.BytesValue)
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
+ // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.BytesValue)
MergeFrom(*source);
}
}
void BytesValue::MergeFrom(const BytesValue& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.value().size() > 0) {
set_value(from.value());
@@ -2572,12 +2645,14 @@ void BytesValue::MergeFrom(const BytesValue& from) {
}
void BytesValue::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.BytesValue)
if (&from == this) return;
Clear();
MergeFrom(from);
}
void BytesValue::CopyFrom(const BytesValue& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BytesValue)
if (&from == this) return;
Clear();
MergeFrom(from);
@@ -2653,10 +2728,12 @@ void BytesValue::clear_value() {
return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
::std::string* BytesValue::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)
return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
::std::string* BytesValue::unsafe_arena_release_value() {
+ // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value)
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
@@ -2682,7 +2759,7 @@ void BytesValue::clear_value() {
}
value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
value, GetArenaNoVirtual());
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 7dca938c..10784778 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -1048,10 +1048,12 @@ inline ::std::string* StringValue::mutable_value() {
return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* StringValue::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value)
return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* StringValue::unsafe_arena_release_value() {
+ // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.StringValue.value)
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
@@ -1077,7 +1079,7 @@ inline void StringValue::unsafe_arena_set_allocated_value(
}
value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
value, GetArenaNoVirtual());
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value)
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.StringValue.value)
}
// -------------------------------------------------------------------
@@ -1116,10 +1118,12 @@ inline ::std::string* BytesValue::mutable_value() {
return value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* BytesValue::release_value() {
+ // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)
return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* BytesValue::unsafe_arena_release_value() {
+ // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.BytesValue.value)
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
return value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
@@ -1145,7 +1149,7 @@ inline void BytesValue::unsafe_arena_set_allocated_value(
}
value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
value, GetArenaNoVirtual());
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value)
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index 040d8a24..4828ad9a 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -39,6 +39,7 @@ package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/wrappers";
option java_package = "com.google.protobuf";
option java_outer_classname = "WrappersProto";
option java_multiple_files = true;